STM32 使用 DMA 在环形缓冲区中实现 UART 不定长接收时,如何精确区分帧边界与数据中的 0x0D 0x0A?

· 1 浏览

回答(4)

用双缓冲(乒乓)代替环形,DMA半满/全满中断分别处理,配合超时判断,可减少数据竞争,但需注意内存占用和中断优先级。
硬件工程师Leo · 2026-08-27
可以定义帧头为0xAA 0x55,帧尾为0x0D 0x0A,并在数据中若出现帧头或帧尾则插入转义字节(如0x1B),接收时反向还原,简单可靠。
嵌入式老白 · 2026-08-27
建议用DMA+空闲中断+状态机:空闲中断标志帧结束,然后从缓冲区头开始解析,遇到0x0D 0x0A时检查前一字节是否为帧尾标志(如0xAA),否则视为数据。
码农小张 · 2026-08-27
在STM32的UART DMA环形缓冲区中,区分帧边界与数据内的0x0D 0x0A,核心思路是采用“帧头+长度”或“超时+帧尾”策略,而非单纯依赖字节内容。推荐做法:1) 定义帧格式,如[帧头0xAA][长度][数据][CRC],接收时先通过DMA空闲中断(IDLE)判断一帧结束,再在缓冲区中扫描帧头,用长度字段精确切帧,这样即使数据含0x0D 0x0A也不会误判。2) 若必须使用0x0D 0x0A作为帧尾,需配合超时机制:在空闲中断后,检查缓冲区尾部是否连续出现0x0D 0x0A,且设置一个短超时(如3ms)来确认帧结束,避免数据中偶然的相同字节触发。3) 实操建议:启用DMA的循环模式,维护读/写索引,在IDLE中断中更新写索引,主循环或中断中解析;同时,对数据中的0x0D 0x0A做转义(如0x7D 0x5E),或使用位填充,但会增加开销。最稳妥的是采用长度字段,彻底规避歧义。
mcuku 阿沐 · 2026-08-27