STM32 使用DMA+双缓冲串口接收不定长数据时,如何避免缓冲区切换瞬间丢包?

· 1 浏览

回答(4)

如果使用RTOS,可将DMA中断中数据拷贝到队列,由任务处理,避免在中断中做耗时操作,减少丢包风险。
RTOS爱好者 · 2026-08-27
可以用空闲中断+DMA循环模式,不用双缓冲,直接环形队列,简单且不易丢包。双缓冲适合高吞吐场景。
码农小刘 · 2026-08-27
注意DMA双缓冲切换时,要确保在TC中断里先读CNDTR再改地址,否则可能覆盖未处理数据。建议用临界区保护切换操作。
嵌入式老张 · 2026-08-27
核心思路是让DMA始终处于接收状态,避免在切换缓冲区时关闭DMA。推荐使用STM32的DMA双缓冲模式(DBM),配合空闲中断(IDLE)或超时定时器判断帧结束。具体操作:初始化时配置DMA为循环模式(Circular)并启用双缓冲,两个缓冲区地址分别设为DMA_Memory0和DMA_Memory1。当DMA传输完成中断(TC)触发时,不要停止DMA,而是立即交换当前使用的缓冲区指针(通过修改DMA_CNDTR和内存地址),同时将已满的缓冲区数据拷贝到应用层。关键点:在中断服务函数中,先读取DMA当前剩余计数(DMA_GetCurrDataCounter)确定数据位置,再切换缓冲区,确保切换瞬间DMA仍在写入另一个缓冲区,不会丢包。实操建议:使用HAL库时,可调用HAL_DMAEx_MultiBufferStart_IT配置双缓冲,并在XferCpltCallback中处理数据;同时启用串口空闲中断(UART_IDLE)来标记一帧结束,避免频繁中断。若需更高可靠性,可增加一个环形缓冲区,将DMA数据先暂存,再由应用层按帧解析。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

🔗 波特率计算器