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

· 2 浏览

回答(4)

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

🧰 配套工具

🔗 波特率计算器