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

· 4 浏览

回答(4)

补充:硬件上可加RS485方向控制或使用FIFO芯片,但软件上更稳的是用DMA的传输完成中断配合超时定时器(如TIM),在超时后处理,避免IDLE误触发。
老周谈嵌入式 · 2026-08-27
补充:若担心禁用DMA丢字节,可改用“双缓冲+软件切换”策略:在IDLE中断中只置标志,主循环轮询处理,但需保证主循环响应时间小于帧间隔,否则仍会丢。
嵌入式小飞侠 · 2026-08-27
补充:在IDLE中断里用DMA_GetCurrDataCounter计算已接收长度,但注意该值在DMA循环模式下是剩余未传输字节数,需用缓冲总长减去,且要防止溢出,建议用volatile变量记录。
代码匠老王 · 2026-08-27
核心思路:用DMA双缓冲(如DMA_CIRCULAR模式)配合空闲中断(IDLE)和乒乓标志位,在切换瞬间不依赖DMA半满/全满中断,而是由IDLE触发处理。实操建议:1) 配置DMA为循环模式,两个缓冲区各256字节,使能DMA传输完成中断(半满/全满)和USART_IDLE中断;2) 在IDLE中断中,读取DMA当前数据指针(DMA_GetCurrDataCounter),据此确定当前写入哪个缓冲,并立即处理另一个缓冲(即“非当前”缓冲),同时清零IDLE标志;3) 切换瞬间丢包主因是处理缓冲时DMA仍在写同一缓冲,因此需在IDLE中断中先禁用DMA(或USART)短暂时间,拷贝数据后重新使能,但禁用时间需小于一个字节传输时间(如115200bps下约87us),可用临界区或直接操作寄存器实现;4) 若数据率较高,建议增大缓冲或改用FIFO+双缓冲,并确保处理函数轻量。关键:IDLE中断是“数据停止”信号,天然避免乒乓切换冲突,比仅靠半满中断更可靠。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

🔗 波特率计算器