stm32F407串口通信Sample

stm32的串口,是很方便实验连接电脑的方式之一,大部分开发板都是串口通过ch340转接至电脑usb接口。

一、任务目标

  1. 通过串口向电脑发送消息,并控制led7的开关;
  2. 电脑通过串口向开发板发送消息,并控制led8的开关

二、硬件

  1. LED7<-->PF7:发送消息时闪烁
  2. LED8<-->PF8:接收到消息时闪烁
  3. USART1_TX<-->PA9:USART1的发送引脚,与PA9复用
  4. USART1_RX<-->PA10:USART1的接收引脚,与PA10服用
  5. USART1串口在我这个开发板上,是通过ch340转换为usb连接电脑上的
  6. RST按键用于复位,否则开发板上电即发送消息,串口无法调试

三、工具

  1. flymcu:烧录工具
  2. comtransmit:串口调试工具,用于接收和发送数据

四、配置

  1. sys,rcc同之前的默认设置;
  2. GPIO:两个LED等连接PF7/8,通用输出配置,无需其他设置
  3. USART1:在Connectivity标签下的USART1接口配置
    • 模式(mode):设置为异步模式(Asynchronous)
    • Parameter settings:波特率(baud rate):9600;字节长度(word length)8位;无校验位(parity);停止位(stop bits)为1;通信方向(data direction)为双向;
    • NVIC settings:启用USART1的全局中断功能
    • GPIO settings:GPIO MODE:PA9/10均设置为端口复用(Alternate function),注意,这里和开发板的教程不同,无需设置上拉/下拉模式,使用推挽模式即可。

五、运行流程

同之前的中断程序运行流程类似,通过调用回调函数实现功能(非阻塞模式)

main.c-->stm32f4xx_hal_uart.c-->main.c

main.c

  1. 发送消息(阻塞式)

    这里先演示阻塞式发送消息,操作非常简单,只需要调用HAL_UART_Transmit函数即可。

led7_on();
HAL_UART_Transmit(&huart1, tx_led_open, sizeof(tx_led_open), 10000);
led7_off();
  1. 接收消息(非阻塞式,接收基本非阻塞式的)

    在main.c中调用HAL_UART_Receive_IT函数。

  //usart1接收到数据后,将数据存放在rx_data中
  HAL_UART_Receive_IT(&huart1, &rx_data, 1);

stm32f4xx_hal_uart.c

USART的发送、接收函数均在此文件中,如上面main.c文件中调用的发送和接收消息函数 此文件在driver目录的src下 几乎所有的usart的执行都在这个文件中,接收的函数运行流程执行如下:

  1. HAL_UART_Receive_IT-->UART_Start_Receive_IT-->UART_Receive_IT-->HAL_UART_RxCpltCallback
  2. HAL_UART_RxCpltCallback是接收消息的虚函数,HAL_UART_Receive_IT就是通过回调此函数实现消息接收后的操作。如:消息接收后,点亮LED8灯
  3. 剩下就是需要重写HAL_UART_RxCpltCallback函数即可

main.c

由于在main函数中调用HAL_UART_Receive_IT后,是通过重写回调函数HAL_UART_RxCpltCallback来实现的。

  1. 在回调函数中首先要判断接收的消息是否来自USART1端口
  2. 对接收到的信息进行分析,然后根据信息开关led8
  3. 仔细观察代码中,HAL_UART_Receive_IT函数在每次发送消息完毕之后,都会再调用一次,目的是为了一直在监听是否有接收到消息。 代码如下:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if(huart->Instance==USART1) {
        if(rx_data=='a') {
            led8_on();

            led7_on();
            HAL_UART_Transmit(&huart1, tx_led_open, sizeof(tx_led_open), 10000);
            led7_off();
            HAL_UART_Receive_IT(&huart1, &rx_data, 1);

        } else if(rx_data=='b') {
            led8_off();

            led7_on();
            HAL_UART_Transmit(&huart1, tx_led_close, sizeof(tx_led_close), 10000);
            led7_off();
            HAL_UART_Receive_IT(&huart1, &rx_data, 1);
        }
    }
}

六、其他

  1. 其实这个例程非常简单,无非是配置USART端口,然后重写回调函数,实现功能;
  2. 这里有一个排查了很久的问题:if(rx_data=='a'),这个语句弄了很久,目前我的单片机上,必须比较字符,无法直接比较0x这种形式的16进制(功力不够,没找到原因)
  3. 注意调试工具的参数要和usart配置参数一直,另外就是调试工具和程序下载工具不能同时使用,当调试工具端口打开后,程序下载工具是无法下载程序的。

七、函数说明

发送函数

  1. 阻塞式发送函数
    HAL_StatusTypeDef  HAL_UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size, uint32_t Timeout)
    
  • 参数1:huart,串口实例的指针。
  • 参数2:*pData,待发送数据缓冲区的指针。
  • 参数3:Size,待发送数据的字节数。
  • 参数4:Timeout,超时时间值。
  1. 非阻塞式发送函数
    HAL_StatusTypeDef  HAL_UART_Transmit_IT(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size);
    
  • 参数1:huart,串口实例的指针。
  • 参数2:*pData,待发送数据缓冲区的指针。
  • 参数3:Size,待发送数据的字节数。
  1. 非阻塞式发送完毕中断回调函数
    //发送完毕后回调中断函数
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef  *huart);
    //发送一半回调
    void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef  *huart)
    

接收函数

  1. 非阻塞式接收函数(推荐使用)

    HAL_StatusTypeDef  HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size);
    
    • 参数1:huart,串口实例的指针。
    • 参数2:*pData,数据接收据缓冲区的指针。
    • 参数3:Size,待接收数据的字节数。
  2. 接收完毕中断回调函数

    //发送完毕回调中断函数
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart);
    //接收一半回调中断函数
    void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef  *huart);
    

results matching ""

    No results matching ""

    results matching ""

      No results matching ""