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

· 2 浏览

回答(4)

如果MCU支持,用硬件FIFO或UART的RTO(接收超时)功能替代IDLE,时序更稳。双缓冲切换时,建议在临界区(关中断)内完成指针更新,防止DMA中断嵌套。
硬件老张 · 2026-09-03
可以开启DMA的传输错误中断,若切换时发生FIFO溢出,能及时捕获。另外,将缓冲大小设为2的幂次,用位运算判断当前缓冲,减少切换延迟。
嵌入式小飞侠 · 2026-09-03
建议用HAL的HAL_UARTEx_ReceiveToIdle_DMA配合双缓冲,它内部已处理IDLE和半传输,但需注意在回调里先调用HAL_UARTEx_ReceiveToIdle_Stop再重新启动,否则可能丢尾字节。
码农老王 · 2026-09-03
核心思路是让DMA始终处于接收状态,用空闲中断(IDLE)配合双缓冲切换,并在切换时先读DMA剩余计数(DMA_GetCurrDataCounter)再操作缓冲。具体实操:1)配置DMA为循环模式,双缓冲地址A/B,使能IDLE中断;2)在IDLE中断里,先读取当前DMA目标缓冲索引和剩余计数,确定数据落在哪个缓冲及长度;3)切换时,先关闭DMA(或暂停),更新缓冲指针,再重新使能,避免硬件写指针与软件读指针冲突。关键技巧:不要用普通半传输/传输完成中断来切缓冲,因为不定长数据可能中途停止,IDLE才是触发点。若担心切换瞬间丢字节,可加一层FIFO或乒乓缓冲,在IDLE处理时用memcpy快速搬移,并确保DMA循环模式不停止,仅切换目标地址。实测中,切换前先读计数器可精确知道已收字节,避免覆盖。
mcuku 阿沐 · 2026-09-03

🧰 配套工具

🔗 波特率计算器