STM32 使用 DMA + 双缓冲接收不定长串口数据时,如何避免缓存覆盖与丢帧?

· 1 浏览

回答(4)

补充:在空闲中断中,务必清除IDLE标志(先读SR再读DR),否则会反复触发,导致处理混乱。
硬件工程师阿强 · 2026-08-27
补充:若数据量较大,可考虑使用DMA的乒乓缓冲(硬件自动切换),减少中断开销,但需注意缓冲区大小和内存对齐。
码农小刘 · 2026-08-27
补充:使用双缓冲时,注意DMA的传输完成中断和空闲中断的优先级,建议空闲中断优先级更高,确保帧边界及时处理。
嵌入式老张 · 2026-08-27
核心方案是采用“双缓冲 + 空闲中断”机制,并配合环形队列或状态机。首先,配置两个DMA缓冲区(如BufferA/BufferB),使用DMA的循环模式或双缓冲模式(STM32的DMA支持双缓冲切换,通过CTRL寄存器控制)。当DMA传输完一个缓冲区时,触发传输完成中断,在中断中立即切换DMA到另一个缓冲区(若硬件双缓冲则自动切换),同时将已满缓冲区数据拷贝到应用层环形队列,并记录长度。为避免覆盖,务必在中断中快速处理(仅拷贝指针或数据),主循环中再解析。对于不定长数据,建议启用串口空闲中断(IDLE):当总线空闲时,触发中断,此时DMA已接收完当前帧,可读取DMA剩余计数(NDTR)计算实际接收长度,并复位DMA指针。关键点:1) 确保DMA缓冲区大小大于最大帧长,且两缓冲区交替使用,防止写覆盖;2) 在空闲中断中处理帧边界,避免丢帧;3) 若使用循环模式,需在空闲中断中记录当前写入位置,并防止DMA覆盖未读数据。实操建议:使用STM32CubeMX配置DMA为循环模式,开启IDLE中断,在中断中读取NDTR并拷贝数据到环形缓冲区,主循环解析。测试时,用串口助手发送不同长度数据验证。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

🔗 波特率计算器