描述

这一篇文章是关于stm32的串口中断学习,主要是利用CubeMX对stm32进行配置,使用串口消息收发,完成一些传感器的消息接收。

本篇文章最后能达到的效果就是,可以向单片机发送需要的数据,并可以从连接在单片机上的传感器上,返回检测到的结果

  • 研发平台:淘宝上购买的野火店铺的一款单片机,名字叫骄阳开发板,核心芯片是
    stm32F407IGT6
  • 开发器件:本文还使用了一种传感器,是在淘宝上购买的,是NFC卡识别模块。需要链接的话可以私信我,在这里就不贴出来了。

学习步骤

  1. 各个传感器是如何工作的,它们如何连接到stm32上
  2. 对传感器进行设置
  3. 在单片机上设置usart端口
  4. 连接传感器
  5. 进行测试
  • 传感器厂商一般会提供的:
    针对购买到的传感器,厂商一般会提供一本说明书,及能够正常打开它所需的驱动软件,及厂商提供的界面软件。通过界面软件,可以完成一些传感器最基本的调用及测试需求。
  • 关于如何学习购买到的传感器模块:
    查阅说明书,首先要确定一些基本信息:多少V供电?通信的各个参数是什么?这样可以保证我们能顺利的将模块连接到单片机上。
    接下来我们还需要确定的是,与模块的通信指令是什么?这些通信指令及格式一般都是由制造模块的厂商设定好的,我们不能更改也无需更改,只需要会用即可。
    最后我们需要了解的是,传感器是如何检测信息的?这涉及到是否我们需要额外的操作,例如NFC卡识别模块就额外需要对空白卡片进行读写。检测到的信息,该如何解析成我们需要的数据?

    NFC模块

    1. 学习

    首先我买到的NFC模块的类型是——串口UART TTL接口,也就是说该模块是通过串口通信TTL电平的方式与单片机完成通信的。

该模块上留有四个管脚,分别写着:GND、B/RXD、A/TXD、VCC。查阅说明手册,我们得知该模块使用的是串口通讯。模块标配 3.6V-5V 供电,一般 5V 供电,TTL 电平(0~3.3V), 初始波特率是 9600,8 位数据位,1 位结束位,无奇偶校
验。模块默认为读写模式,可以发命令切换为只读模式,模式配置会保存,只读模式下模块会
主动发送识别到的卡 UID 卡号。

2. 目标

我们希望达到的效果,就是当卡片靠近我们的模块时,我们可以自动的得到卡片的信息和ID。

3. 研发

了解到这些,我们可以开始配置这个NFC模块了

  1. 首先我的手上是有这样一个模块,该模块是TTL转USB的。我们将NFC模块连接到这个串口转USB模块上,再将USB接口连接到电脑上,就可以正常和串口进行通信了。
    连接的方式如下:
    NFC模块的RXD——转换模块的TXD
    NFC模块的TXD——转换模块的RXD
    NFC模块的GND——转换模块的GND
    NFC模块的VCC——转换模块的VCC

  2. 将USB接口连接到电脑上后,我们应该能正常看到出现一个新的COM口,转换模块的状态灯是正确的。

  3. 接下来,我们打开了官方提供的UI软件,根据说明书所说,该模块默认的模式是读写模式。因此我们在软件中找到了一个按钮——“一键读卡”。该模块有一些安全性的设置,例如验证模式需要输入对应的密码KEYA和KEYB等。这里,不对这些特殊内容进行过多介绍。事实上在我开发的过程中,这些设置也一直是保持默认状态没有更改的。我们这里只讨论一些和项目有直接关联的知识。
  4. 我们点击“一键读卡”,在软件窗口中传感器返回了这样的数据“00..00”(一共32个0)。按照说明书上所说,我们目前读取的是块号1上的数据。
  5. 什么意思呢,我们这样理解,该模块内部实际上有64个数据块,每个数据块上呢又有16个字节的数据。我们刚刚读取到的32个0都是十六进制下的数据,一个字节等于8位二进制,也就等于2位十六进制的数据。
  6. 根据我们的目标,我们需要卡片在靠近识别模块时,自动的返回卡片ID。如果我们在块号1上,写上数据,并且设置识别模块的运行模式为,自动读取固定块号的数据的模式。当我们拿到指定块号的数据后,再对数据进行解析,我们不就可以实现我们的目标了吗
  7. 因此我们可以这样做:往空白卡片的块XX上,写上一个数据XX。随后将模块设置为自动读取块XX的模式,最后再在单片机收到数据时,将数据解析出来得到数据XX。这就是我的完整逻辑了。我的实际做法是,我有100张卡,在每个空白卡片的块01上,写上截然不同的标识。例如,我们往第90个卡片的块01写上了数据“00..005A”(30个0+5A),这实际上就是16个字节的数据,只不过前15个字节的数据是0.

研发步骤

  1. 像之前一样,打开CubeMX工程,找到你使用的芯片并新建工程
  2. 翻阅数据手册,找到USB转串口的端口,该端口用于消息的发送及接收;我们从数据手册中发现,该端口是PB6和PB7。
  3. 另外我们还需要另外一组USART端口,用于接收NFC模块的数据。经过翻阅手册,我们发现这两个端口是PC6和PC7。
  4. 我们在CubeMX界面左侧的“Connectivity”中找到“USART1”和“USART6”,将它们的Mode选项从“Disable”变为“Asynchronous”,并且注意,将“USART6”的“Baud Rate”波特率从默认的“115200”变为“9600”(NFC模块手册标注了这项信息)



  5. 按照之前的设置生成代码,得到工程
  6. 接下来,在工程中做出如下的修改
    usart.c中的头文件用户定义部分添加

     #include "stm32f4xx_hal.h"
     #include <stdio.h>
    

    usart.c用户代码部分添加

     int fputc(int ch, FILE *f)
     {
       HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
       return ch;
     }
     int fgetc(FILE *f)
     {
       uint8_t ch = 0;
       HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
       return ch;
     }
    

    main.c中的头文件用户定义部分添加

     #include <stdio.h>
     #include <string.h>
    
     #define RXBUFFERSIZE  256     
     char info_buffer[RXBUFFERSIZE];   
     uint8_t aRxBuffer;            
     uint8_t Uart1_Rx_Cnt = 0;    
    
     #define CARD_BUFFER_LEN 16
     uint8_t card_buffer[CARD_BUFFER_LEN];
     uint8_t Uart6_Rx_Cnt = 0;
    

    main.c中的主函数用户定义部分添加

     HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
     HAL_UART_Receive_IT(&huart6, card_buffer, CARD_BUFFER_LEN);
     printf("hello! FUXI ROBOT!\n");
    

    main.c中的用户代码定义部分添加

     void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
     {
       UNUSED(huart);
         if (huart == &huart1)
         {
             if(Uart1_Rx_Cnt >= 255)
             {
                 Uart1_Rx_Cnt = 0;
                 memset(info_buffer,0x00,sizeof(info_buffer));
                 HAL_UART_Transmit(&huart1, (uint8_t *)"Data overflow!", 10,0xFFFF);     
    
             }
             else
             {
                 info_buffer[Uart1_Rx_Cnt++] = aRxBuffer;  
    
                 if((info_buffer[Uart1_Rx_Cnt-1] == 0x0A)&&(info_buffer[Uart1_Rx_Cnt-2] == 0x0D)) 
                 {
                     HAL_UART_Transmit(&huart1, (uint8_t *)&info_buffer, Uart1_Rx_Cnt,0xFFFF); 
                     while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);
                     Uart1_Rx_Cnt = 0;
                     memset(info_buffer,0x00,sizeof(info_buffer)); 
                 }
             }
             HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); 
         }
         if (huart == &huart6)
         {
    
             uint8_t card_id = card_buffer[15];
             printf("read card %d!\n", card_id);
             HAL_UART_Receive_IT(&huart6, card_buffer, CARD_BUFFER_LEN);
         }
     }
    
  7. 以上代码的添加位置的截图如下。
    usart.c中添加


    main.c中添加


  8. 将模块的RXD接到stm32的TXD(PC6管脚)上,将模块的TXD接到stm32的RXD上(PC7管脚)上,然后模块GND和VCC分别接到stm32的GND和5V上,这样完成了模块的连接

  9. 将单片机与电脑,通过USB转串口那条线连接起来(USB接口接到电脑上),打开串口助手并打开端口。按下复位键串口会返回我们设置好的信息。将写好的卡片放在模块上,模块会返回卡片的标号,我们在空白窗口写下我们想对单片机发送的字符串,勾选“发送新行”并点击“发送数据”,stm32会将信息原封不动的返回。于是我们完成了这项工作的开发与学习。

总结

这篇文章,通过CubeMx设置USART的端口,并在代码中添加了一些数据读取后的处理。最终实现了基于串口TTL通信的NFC模块数据读取,并且实现了串口的自定义字符串发送与接收。