深入解析STM32 UART通信及代码编写技巧

文章目录

  • 前言
  • 一、查询方式编写串口发送和接收的代码
  • 二、中断方式编写串口发送和接收的代码
  • 总结

  • 前言

    本篇文章来给大家讲解USART的代码详细讲解和使用步骤。

    一、查询方式编写串口发送和接收的代码


    串口查询发送函数:

    HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
    

    参数:
    huart(UART_HandleTypeDef 结构体指针): 这是一个指向 UART_HandleTypeDef 结构体的指针,该结构体包含了UART相关的配置信息,例如UART的硬件寄存器基地址、波特率、数据位数等。

    pData(uint8_t 指针): 这是一个指向要发送数据缓冲区的指针。

    Size(uint16_t 类型): 这是要发送的数据的字节数。

    Timeout(uint32_t 类型): 这是发送数据的超时时间,单位是毫秒。如果设置为 HAL_MAX_DELAY,则表示无限等待。

    返回值:
    函数的返回值是 HAL_StatusTypeDef 类型,表示函数执行的状态。可能的返回值包括:

    HAL_OK: 操作成功完成。
    HAL_BUSY: 操作正在进行中,不能启动新的操作。
    HAL_ERROR: 操作失败。

    函数作用:
    HAL_UART_Transmit 函数的主要作用是通过UART发送数据。它接收一个指向要发送数据的缓冲区的指针和数据的字节数,然后将这些数据通过配置好的UART通道发送出去。函数会根据配置的超时时间等待发送完成或超时。

    HAL_UART_Transmit函数内部机制讲解:

    这里只讲解比较重要的代码部分

        while (huart->TxXferCount > 0U)
        {
          if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
          {
            return HAL_TIMEOUT;
          }
          if (pdata8bits == NULL)
          {
            huart->Instance->DR = (uint16_t)(*pdata16bits & 0x01FFU);
            pdata16bits++;
          }
          else
          {
            huart->Instance->DR = (uint8_t)(*pdata8bits & 0xFFU);
            pdata8bits++;
          }
          huart->TxXferCount--;
        }
    

    上面代码的解读:

    1.首先先检查要发送的数据是否大于0

    2.检查TXE寄存器,判断TDR寄存器中的数据是否被发送出去

    3.把数据写入DR数据寄存器中

    4.让TxXferCount数据量减1

    使用示例:

    HAL_UART_Transmit(&huart1, "Hello World", sizeof("Hello World"), 1000);
    

    串口查询接收函数:

    HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
    

    参数:
    huart:UART 句柄,指定了你要使用的 UART 外设。

    pData:指向要存储接收到数据的缓冲区的指针。

    Size:要接收的数据的数量,以字节为单位。

    Timeout:超时时间,以毫秒为单位。如果在超时时间内没有接收到足够的数据,则函数会返回。可以使用 HAL_MAX_DELAY 作为超时参数来指定无限超时,直到接收到足够的数据。

    返回值:
    函数的返回值是一个 HAL_StatusTypeDef 类型的枚举值,表示函数执行的结果。可能的返回值包括:

    HAL_OK:函数执行成功,接收到了指定数量的数据。

    HAL_TIMEOUT:超时,未能在指定的时间内接收到足够的数据。

    HAL_ERROR:发生了错误,可能是由于参数错误或者硬件问题引起的。

    上面代码的解读:

    1.首先先检查要接收的数据是否大于0

    2.检查RXNE寄存器,判断RDR寄存器中是否有数据可以接收

    3.将DR中的数据读取出来

    4.让RxXferCount数据量减1

    使用示例:

    uint8_t rx_data[10]; // 接收数据缓冲区
    
    while (1)
    {
        HAL_UART_Receive(&huart1, rx_data, sizeof(rx_data), HAL_MAX_DELAY);
    
        // 处理接收到的数据
        // 可以在这里进行数据处理或者将数据发送到其他地方
    }
    

    二、中断方式编写串口发送和接收的代码

    开启中断:

    串口发送函数(中断方式)

    HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
    

    参数:
    huart:UART 句柄,指定了你要使用的 UART 外设。

    pData:指向要传输的数据缓冲区的指针。

    Size:要传输的数据的数量,以字节为单位。

    返回值:
    函数的返回值是一个 HAL_StatusTypeDef 类型的枚举值,表示函数执行的结果。可能的返回值包括:

    HAL_OK:函数执行成功,数据已经被成功传输。

    HAL_ERROR:发生了错误,可能是由于参数错误或者硬件问题引起的。

    HAL_BUSY:UART 外设忙,不能执行传输。

    HAL_TIMEOUT:超时,传输未能在指定的时间内完成。

    HAL_UART_Transmit_IT函数调用的分析:

    HAL_UART_Transmit_IT函数并没有直接进行数据的发送而是开启TEX发送数据寄存器空中断。

    串口1中断函数:

    在HAL_UART_IRQHandler函数中调用了UART_EndTransmit_IT。

    发送完最后一个数据后使能TC发送完成中断。


    发送最后一个数据完成调用HAL_UART_TxCpltCallback回调函数:

    串口中断发送数据方式总结:

    1.使能TXE中断,将数据一个个的发送出去。

    2.当只有最后一个数据的时候使能TC发送完成中断

    3.当最后一个数据发送完成后调用HAL_UART_TxCpltCallback回调函数。

    使用示例:

    
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    {
        if (huart == &huart1)
        {
            // 发送完成回调函数
        }
    }
    
    
    HAL_UART_Transmit_IT(&huart1, tx_data, strlen((char *)tx_data)); // 发送数据
    

    串口接收函数(中断方式)

    HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
    

    参数:

    huart:一个指向 UART_HandleTypeDef 结构体的指针,该结构体包含了 UART 外设的配置和状态信息。
    pData:一个指向要存储接收数据的缓冲区的指针。
    Size:要接收的数据的字节数。

    返回值 (HAL_StatusTypeDef):该函数返回一个 HAL_StatusTypeDef 类型的值,用于表示函数执行的状态。可能的返回值包括:

    HAL_OK:函数执行成功。
    HAL_BUSY:UART 正在忙于处理其他操作。
    HAL_ERROR:发生了错误,导致函数执行失败。
    HAL_TIMEOUT:函数执行超时。

    HAL_UART_Receive_IT函数会马上返回不会一直等待到有数据才返回。

    在UART_Start_Receive_IT中调用__HAL_UART_ENABLE_IT函数开启RXNE中断。


    接收数据:

    当接收数据完成后会调用HAL_UART_RxCpltCallback回调函数:

    uint8_t rx_data = 0;
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        if (huart == &huart1)
        {
            // 处理接收到的数据
            // 可以在这里进行数据处理或者将数据发送到其他地方
            HAL_UART_Receive_IT(&huart1, rx_data, 1); // 继续接收下一个字节
        }
    }
    
    HAL_UART_Receive_IT(&huart1, rx_data, 1); // 启动接收中断,每次接收一个字节
    

    总结

    本篇文章深入的讲解了UART发送和接收查询方式和中断方式的具体函数使用和内部原理。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入解析STM32 UART通信及代码编写技巧

    发表评论