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

· 1 浏览

回答(4)

切换时建议先禁用DMA(清EN位),修改地址后重新使能,并确保在USART的RXNE中断之前完成,否则可能丢失新到的字节。
硬件控阿强 · 2026-08-27
如果数据帧较长,可考虑使用DMA的传输完成中断(TC)来切换,但需配合超时机制;对于短帧,IDLE中断更可靠,因为TC可能不触发。
码农小王 · 2026-08-27
可以用环形缓冲区替代双缓冲,DMA连续写入,通过读指针和写指针管理,避免切换,但需注意内存访问冲突,建议用内存屏障或关中断保护。
嵌入式老张 · 2026-08-27
核心思路是让DMA始终处于接收状态,通过双缓冲乒乓切换并配合空闲中断(IDLE)或定时器超时来判断帧结束。具体做法:配置两个缓冲区(如buf1和buf2),DMA循环模式或半满/全满中断切换,同时开启USART的IDLE中断。当收到数据时,DMA写入当前缓冲区;若触发半满或全满中断,立即切换DMA目标地址到另一缓冲区,并处理已满缓冲区数据。关键在于切换瞬间:在中断服务函数中,先读取DMA的CNDTR寄存器(剩余字节数)以确定已接收长度,再修改DMA的M0AR/M1AR(或内存地址)指向另一缓冲区,并重新使能DMA(若用循环模式则无需重使能)。为避免丢包,切换操作必须在DMA下一次传输前完成,因此中断优先级要高于串口中断,且处理逻辑要精简。此外,利用IDLE中断标记帧结束,在IDLE中断中根据当前DMA状态处理最后一段数据。实操建议:使用STM32CubeMX生成代码,开启DMA循环模式+IDLE中断,在中断回调中处理切换;测试时用逻辑分析仪观察时序,确保切换延迟小于一个字节传输时间(如115200波特率下约87us)。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

🔗 波特率计算器