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

· 5 浏览

回答(4)

考虑硬件流控(RTS/CTS)作为最后防线。若帧长不定且突发量大,软件双缓冲可能不够,可扩展为4缓冲或动态链表。另外,用定时器测量帧间隔(如3.5字符时间)作为帧结束判据,比空闲中断更可靠,尤其在高波特率下。
芯海拾贝 · 2026-09-04
丢帧常因中断优先级配置不当。将DMA和串口空闲中断优先级设为最高,且开启DMA的传输错误中断。若使用RTOS,用二值信号量通知任务,但需确保任务处理速度>接收峰值速率,否则加流控或增大缓冲。
嵌入式小飞侠 · 2026-09-04
建议用空闲中断+DMA的循环模式,但别依赖半/全传输中断切换,因为不定长帧可能跨边界。更稳的是:空闲中断时,用DMA的CNDTR计算当前接收位置,再结合上次位置判断帧是否完整,直接memcpy到环形缓冲。
老码农阿强 · 2026-09-04
核心思路是采用“双缓冲+空闲中断+DMA传输完成中断”的三级联动机制。首先,将DMA配置为循环模式,并设置两个大小相等的缓冲区(如BUFF_A和BUFF_B),通过DMA的半传输和全传输中断来切换当前写入缓冲区。当串口空闲中断(IDLE)触发时,立即读取DMA的当前数据计数器(NDTR),结合已切换的缓冲区指针,即可确定完整帧的起始和长度。为避免覆盖,需在中断服务中快速拷贝数据到应用层队列,并确保处理时间短于下一帧到达间隔。实操建议:1)使用双缓冲时,务必在DMA传输完成中断中置标志位,主循环轮询处理,避免在中断内做耗时操作;2)空闲中断需在接收每字节后由硬件自动清除,但需注意在帧间隔小于1字节时间时可能误触发,可结合超时定时器辅助判断;3)若帧率很高,建议将缓冲区大小设为最大帧长的2倍以上,并启用DMA的FIFO模式(若支持)减少总线竞争。最终,通过信号量或环形队列将数据交给协议解析层,确保无锁或短临界区。
mcuku 阿沐 · 2026-09-04

🧰 配套工具

🔗 波特率计算器