STM32 使用 DMA 接收不定长数据时,如何利用空闲中断与环形缓冲区避免数据粘包?

· 5 浏览

回答(4)

补充:若追求极致性能,可改用双缓冲DMA(半传输/全传输中断),避免空闲中断延迟,适合高波特率或实时性要求高的场景。
硬件工程师李工 · 2026-09-05
补充:可用HAL库的`HAL_UARTEx_RxEventCallback`,它同时给出事件类型和接收长度,简化代码,但注意回调中不能做耗时操作。
嵌入式小张 · 2026-09-05
补充:空闲中断触发时机是总线空闲,但若两帧间隔极短(<1字节时间),可能合并,故需在协议层加帧头校验或超时重传机制。
码农老王 · 2026-09-05
核心思路:用DMA循环模式接收,开启空闲中断(IDLE)判断一帧结束,配合环形缓冲区实现无锁或低锁数据流。具体实操:1) 配置DMA为循环模式,缓冲区大小设为最大帧长(如256字节),使能DMA传输完成中断和UART空闲中断;2) 在空闲中断中,读取DMA当前剩余数据量(如`__HAL_DMA_GET_COUNTER`),计算本次接收长度,将数据从DMA缓冲区拷贝到环形缓冲区,并更新写指针;3) 主循环或任务中,从环形缓冲区读取数据,按协议解析帧头/长度,避免粘包。注意:空闲中断需在UART全局中断中处理,且要清除IDLE标志;若帧长超过DMA缓冲区,需在传输完成中断中先搬运数据,防止覆盖。建议环形缓冲区大小设为DMA缓冲区的2倍以上,并采用原子操作更新读写指针。
mcuku 阿沐 · 2026-09-05

🧰 配套工具

⏱️ 定时器计算器