使用 UART 空闲中断(IDLE) + DMA 接收数据
1. 基本原理
-
空闲中断(IDLE):当 UART 接收数据后,总线在 1 字节传输时间 内无新数据时触发中断。
-
DMA 传输:在后台自动将 UART 接收的数据搬运到内存缓冲区,无需 CPU 干预。
-
协作流程:
-
启动 DMA 接收,持续监听 UART 数据。
-
当数据到达时,DMA 自动填充缓冲区。
-
数据停止传输后,触发空闲中断。
-
在中断中计算实际接收长度,处理数据。
-
2. 硬件与库配置
2.1 硬件使能
-
在 STM32CubeMX 中:
-
启用 UART 的 DMA RX 通道。
-
启用 UART 的 全局中断(NVIC Settings)。
-
2.2 代码配置
// 定义全局变量 #define RX_BUFFER_SIZE 256 uint8_t g_rxBufferDMA[RX_BUFFER_SIZE]; // DMA 接收缓冲区 volatile uint16_t g_rxLength = 0; // 实际接收数据长度// 在 main() 初始化中启动 DMA 接收 void UART_Init(void) { // 启用 UART 空闲中断(需手动添加) __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE); // 启动 DMA 接收 HAL_UART_Receive_DMA(&huart4, g_rxBufferDMA, RX_BUFFER_SIZE); }
CubeIDE图形配置如下


3. 中断处理
// 在 stm32xx_it.c 的 USARTx_IRQHandler 中添加空闲中断判断 void USARTx_IRQHandler(void) { HAL_UART_IRQHandler(&huart4); // HAL 库默认中断处理 // 检查并处理错误 if (huart4.ErrorCode != HAL_UART_ERROR_NONE) { if (huart4.ErrorCode & HAL_UART_ERROR_DMA) { // DMA错误特定处理,解决插拔串口或者发送数据频率过导致后DMA缓冲区一直为空的问题 HAL_DMA_Abort(huart4.hdmarx); // 中止DMA通道 HAL_DMA_DeInit(huart4.hdmarx); // 反初始化DMA HAL_DMA_Init(huart4.hdmarx); // 重新初始化DMA } // 清除所有错误标志 __HAL_UART_CLEAR_FLAG(&huart4, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF | UART_CLEAR_IDLEF); huart4.ErrorCode = HAL_UART_ERROR_NONE; // 重置错误码 // 重启DMA接收 HAL_UART_DMAStop(&huart4); memset(g_rxBufferDMA, 0, RX_BUFFER_SIZE); HAL_UART_Receive_DMA(&huart4, g_rxBufferDMA, RX_BUFFER_SIZE); // 立即重启DMA } if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart4); // 清除空闲中断标志 HAL_UART_DMAStop(&huart4);// 停止 DMA 以防止数据覆盖 g_rxLength = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart4.hdmarx);// 计算实际接收的数据长度 //处理串口数据 // ... HAL_UART_Receive_DMA(&huart4, g_rxBufferDMA, RX_BUFFER_SIZE);// 重新启动 UART DMA 接收 } }
通过此方案,可彻底解决轮询接收中的超时问题,同时提升系统整体性能和稳定性。实际部署时需根据硬件特性调整缓冲区和中断优先级。

浙公网安备 33010602011771号