STM32 HAL库USART串口通信详解:发送与不定长数据接收实战指南
目录
STM32 HAL库—USART:串口发送和不定长数据接收
前言:
适用场景:
实现目标:
软硬件环境:
串口通信基础知识:
1. USART(通用同步异步收发器)
2. DMA(直接存储器访问)
USART+DMA 的数据传输流程:
cudemx基础配置:
代码实现(关键部分):
1.数组(缓冲区)定义
2.启动 UART 接收 中断
3. 重定义数据接收中断回调函数
4. 处理数据后回显
测试与验证:
注意要点:
结语:
STM32 HAL库—USART:串口发送和不定长数据接收
前言:
在嵌入式系统中,串口通信(UART) 是最常见的通信方式之一。无论是调试信息的输出,还是设备间的数据交互,UART 都是不可或缺的通信手段。然而,在传统的串口通信中,如果使用阻塞模式进行数据收发,CPU 需要不断轮询状态寄存器,导致资源浪费,并降低系统的响应能力。
为了解决这一问题,我们可以借助 DMA(直接存储器访问) 进行串口数据传输。DMA 允许外设直接访问内存,从而在数据传输过程中释放 CPU 资源,使其能够执行其他任务,提高系统的并行处理能力。本篇博客的目标是分享如何使用 STM32 HAL库 和 CubeIDE,基于 DMA+中断 实现高效的 UART 通信。
适用场景:
本次实验适用于以下应用场景:
需要实时通信的嵌入式系统(如物联网设备、工业控制)
需要高速数据传输,且 CPU 负担较重的应用
需要非阻塞式通信,保证系统主任务流畅运行
实现目标:
-
配置 UART 进行串口通信,实现数据的发送与接收。
-
采用 DMA 进行数据传输,提高系统效率,减少 CPU 负担。
-
结合 中断机制 处理不定长数据,提高数据接收的灵活性。
-
通过 STM32CubeIDE 实现代码编写、下载与调试。
软硬件环境:
开发板:STM32F407 开发板
开发环境:STM32CubeIDE + STM32CubeMX
调试工具:ST-LINK V2
串口工具:USB 转串口模块(CH340G)、串口调试助手(如XCOM)
串口通信基础知识:
在进入实际配置和代码编写之前,我们先回顾一下 UART 和 DMA 的基本概念。
1. USART(通用同步异步收发器)
UART(Universal Asynchronous Receiver/Transmitter)是一种 异步 串行通信协议,它无需同步时钟信号,仅通过起始位、数据位、校验位和停止位进行数据传输。基本参数包括:
波特率(Baud Rate):表示每秒传输的位数,例如 115200 bps。
数据位(Data Bits):一般为 8 位。
校验位(Parity Bit):可选,用于错误检测(本次实验不使用)。
停止位(Stop Bit):表示数据帧结束,一般为 1 位。
STM32 的 UART 采用 串行数据寄存器(DR)、状态寄存器(SR)和控制寄存器(CR) 进行数据收发和控制。
2. DMA(直接存储器访问)
DMA(Direct Memory Access)是一种允许外设直接访问内存的机制,它能够在不经过 CPU 参与的情况下完成数据传输。DMA 的主要特点包括:
降低 CPU 负担,提高系统响应速度。
提高数据传输效率,特别适用于大数据量传输。
支持多通道,可以同时处理多个数据流。
在 STM32 中,DMA 传输方式一般有 外设到内存(接收)、内存到外设(发送)、内存到内存 三种模式。
USART+DMA 的数据传输流程:
为了让数据传输更加高效,我们采用 DMA+中断 结合的方式:
-
发送数据(USART_TX + DMA)
-
在程序中调用
HAL_UART_Transmit_DMA()
函数,将数据从内存传输到 UART 发送缓冲区。 -
DMA 自动完成数据传输,无需 CPU 轮询。
-
接收数据(USART_RX + NVIC)
-
开启USART接收中断。
-
结合
HAL_UARTEx_ReceiveToIdle_IT()
使系统在数据接收完毕(或检测到空闲信号)时触发中断。
cudemx基础配置:
(1)配置系统时钟(选择HSE外部晶振,主频设置为168MHz)。
(2)USART通信配置:
使能RX和TX引脚GPIO时钟和USART时钟;选择异步通信模式,基础配置为波特率115200,8比特(包含校验位),无校验位,一位停止位,接收发送模式。
(3)DMA配置:
打开USART1_TX的DMA通道(系统自动选择对应映射的通道),传输方向为内存到外设。
(4)中断配置:串口一全局中断使能和DMA中断使能。
代码实现(关键部分):
以下是本实验的核心代码逻辑:、
1.数组(缓冲区)定义
#define max_buf 50
uint8_t tx_buf[max_buf]; //待发送的数据数组
uint8_t rx_buf[max_buf]; //存放接收到的数据
uint8_t flag=0; //标志位,是否收到数据
uint8_t length=0; //数据长度
2.启动 UART 接收 中断
/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_IT(&huart1, rx_buf, max_buf);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
3. 重定义数据接收中断回调函数
这里把函数写到了main.c的code4可修改代码块中。先判断中断触发源,并置位标志位,同时获取接受数组长度。(长度是由HAL_UARTEx_RxEventCallback自动计算返回的)
/* USER CODE BEGIN 4 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance==USART1)
{
flag=1;
length=Size;
}
}
/* USER CODE END 4 */
4. 处理数据后回显
本博客中是将数据反转后发出。再次调用HAL_UARTEx_ReceiveToIdle_IT函数接收数据,同时清零标志位。
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(flag==1)
{
for(int i =0;i<length;i++)
{
tx_buf[i] = rx_buf[length -1 - i]; //将数据颠倒
}
tx_buf[length]='\0';
HAL_UART_Transmit_DMA(&huart1,tx_buf, length); //使用DMA发送数据
HAL_UARTEx_ReceiveToIdle_IT(&huart1, rx_buf, max_buf); //接收不定长数据
flag=0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
测试与验证:
-
打开串口调试助手,设置波特率为 115200,数据格式为 8N1。
-
向 STM32 发送数据,STM32 在收到数据后将数据反转后会回显。
-
观察 STM32 输出信息,如果能够正确回显,则表示 DMA+中断结合的串口通信正常工作。
注意要点:
-
DMA 配置要匹配外设:
-
方向要设置正确(内存到外设、外设到内存)。
-
数据宽度需匹配 UART(通常是字节单位)。
-
使用
HAL_UARTEx_ReceiveToIdle_IT()
处理不定长数据。该函数能够在数据接收完成或者检测到空闲帧时,触发中断,适合接受不定长数据,避免固定长度数据带来的问题。
-
避免在中断回调中执行耗时操作。
如果数据量较大,建议将处理逻辑放在主循环中,避免阻塞其他中断。
结语:
本篇博客介绍了 UART 串口通信,并结合 DMA 和中断机制,实现了高效的数据传输方式。通过 DMA,可以让 CPU 专注于其他任务,而中断机制确保了不定长数据的正确接收。这种方法在 物联网、工业自动化 等领域有着广泛的应用。
希望这篇博客能帮到你,如果你在实践中遇到问题,欢迎留言交流!🚀
作者:Open-car