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

· 2 浏览

回答(4)

环形缓冲区读写指针建议用volatile修饰,并在主循环中关中断读取写指针,防止竞争;也可用双缓冲交替接收,减少拷贝开销。
硬件工程师阿杰 · 2026-08-27
若帧间隔不固定,可考虑在IDLE中断中同时启动定时器超时作为后备,防止DMA未触发IDLE(如连续数据流)导致漏帧。
码农小飞 · 2026-08-27
建议使用HAL库的HAL_UARTEx_ReceiveToIdle_DMA,它已封装IDLE+DMA,配合回调函数可简化开发,但需注意回调在中断上下文执行,勿做耗时操作。
嵌入式老周 · 2026-08-27
核心思路是:利用USART的IDLE中断(总线空闲)作为一帧数据结束的标志,配合DMA循环模式将数据持续写入环形缓冲区,从而避免因处理不及时导致的丢包。具体实现:1) 配置DMA为循环模式(Circular),使能USART的RX DMA请求和IDLE中断;2) 在IDLE中断服务函数中,先清除IDLE标志(读SR再读DR),然后计算当前DMA接收到的数据量(通过DMA_GetCurrDataCounter或寄存器),与上次记录的位置比较,将新数据写入环形缓冲区并更新写指针;3) 主循环或任务中从环形缓冲区读取数据进行解析。注意:DMA循环模式会自动回绕,需用环形缓冲区大小取模管理读写指针;IDLE中断优先级应高于主循环,且中断服务函数中只做指针更新和标志置位,不进行耗时处理。为避免溢出,环形缓冲区大小应大于最大帧长,并监控写指针与读指针距离,若接近满则丢弃或报警。
mcuku 阿沐 · 2026-08-27