STM32 使用 DMA 与环形缓冲区实现串口不定长接收时,如何避免缓存覆盖与丢帧?

STM32 · 杜博文智能硬件 · 62 浏览

回答(4)

若丢帧严重,检查DMA优先级和中断嵌套,确保IDLE中断不被更高优先级抢占;也可用双DMA缓冲交替接收,彻底避免覆盖。
硬件控阿杰 · 2026-08-27
可考虑用串口超时(如HAL_UARTEx_RxEventCallback)替代IDLE,更灵活;同时用内存屏障保证中断与主循环间数据一致性。
嵌入式老李 · 2026-08-27
建议用环形缓冲+空闲中断,但注意DMA的循环模式会持续覆盖,务必在IDLE回调中及时更新读指针,并预留至少一个最大帧的余量。
码农小张 · 2026-08-27
电子小兵入门:HAL 库版本差异确实坑,升到新版后很多老问题自动消失了。
★ 精华
核心思路是让DMA持续写入环形缓冲区,同时用空闲中断(IDLE)或超时机制标记帧边界。为避免覆盖,需保证缓冲区大小大于最大帧长,且每次接收后更新写索引(DMA当前传输计数可反推)。实操建议:1)用双缓冲或环形队列,读索引由主循环维护,写索引由DMA中断更新,二者差值即有效数据;2)在IDLE中断中,通过`__HAL_DMA_GET_COUNTER`计算本次接收长度,并立即拷贝数据或置标志,防止DMA继续写覆盖未读数据;3)若帧率极高,可启用DMA传输完成中断(半传输/全传输)配合环形缓冲,分段处理。关键点:确保读速度大于写速度,否则必丢帧;必要时增加缓冲区容量或采用乒乓缓冲。
电子小兵入门 · 2026-08-27
嵌入式老李:这个提醒太及时了,我们正好在调 I2C 时序,试试你的方案。

🧰 配套工具

🔗 波特率计算器