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 64 uint8_t g_rxBuffer[RX_BUFFER_SIZE]; // DMA 接收缓冲区 volatile uint16_t g_rxLength = 0; // 实际接收数据长度 volatile bool g_rxComplete = false; // 接收完成标志// 在 main() 初始化中启动 DMA 接收 void UART_Init(void) {// 启用 UART 空闲中断(需手动添加)__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);// 启动 DMA 接收HAL_UART_Receive_DMA(&huart4, g_rxBuffer, RX_BUFFER_SIZE); }
3. 中断处理
3.1 空闲中断回调
// 在 stm32xx_it.c 的 USARTx_IRQHandler 中添加空闲中断判断 void USARTx_IRQHandler(void) {if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE)) {__HAL_UART_CLEAR_IDLEFLAG(&huart4); // 清除空闲中断标志UART_IdleCallback(&huart4); // 调用自定义处理函数 }HAL_UART_IRQHandler(&huart4); // HAL 库默认中断处理 }
3.2 计算数据长度
// 自定义空闲中断处理函数 void UART_IdleCallback(UART_HandleTypeDef *huart) {if (huart == &huart4) {// 停止 DMA 防止数据覆盖HAL_UART_DMAStop(&huart4);// 计算实际接收数据长度g_rxLength = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);// 设置接收完成标志g_rxComplete = true;} }
4. 数据处理
4.1 主循环中检测标志
while (1) {if (g_rxComplete) {// 处理接收到的数据(例如 "10.00\r\n")char *end = strstr((char*)g_rxBuffer, "\r\n");if (end != NULL) {*end = '\0';float power = atof((char*)g_rxBuffer);usRegInputBuf[Addr_Photo_StateRedLaserPower] = (uint16_t)(power * 10);}// 重置状态并重启 DMA 接收g_rxComplete = false;memset(g_rxBuffer, 0, RX_BUFFER_SIZE);HAL_UART_Receive_DMA(&huart4, g_rxBuffer, RX_BUFFER_SIZE);}// 其他任务osDelay(10); }
5. 关键问题与优化
5.1 数据溢出处理
-
若数据长度超过
RX_BUFFER_SIZE
,DMA 会循环覆盖缓冲区(需根据协议启用/禁用循环模式)。 -
建议在协议中设计数据帧长度限制,或增加动态缓冲区。
5.2 错误处理
// 在 DMA 或 UART 错误中断中恢复接收 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {if (huart == &huart4) {HAL_UART_DMAStop(&huart4);memset(g_rxBuffer, 0, RX_BUFFER_SIZE);HAL_UART_Receive_DMA(&huart4, g_rxBuffer, RX_BUFFER_SIZE);} }
6. 总结
-
优势:
-
非阻塞接收,极大降低 CPU 占用率。
-
自动适应不定长数据帧,无需预设超时时间。
-
高效处理高速数据流(如 115200bps 及以上)。
-
-
适用场景:
-
需要实时响应的工业控制设备。
-
高频数据采集(如传感器网络)。
-
复杂多任务系统(如 RTOS 环境)。
-
通过此方案,可彻底解决轮询接收中的超时问题,同时提升系统整体性能和稳定性。实际部署时需根据硬件特性调整缓冲区和中断优先级。