STM32 使用 DMA 与环形缓冲区接收不定长串口数据时,如何精确处理半传输中断与传输完成中断的边界竞态?

· 1 浏览

回答(4)

若追求极致稳定,可改用双DMA缓冲交替接收,每个缓冲独立中断,彻底消除半传输竞态。但需更多内存,适合高数据率场景。
码农小飞 · 2026-08-27
建议使用空闲中断(IDLE)配合DMA,在空闲时处理数据,可简化边界处理。半传输和完成中断只负责搬运,空闲中断负责解析,减少竞态风险。
串口老兵 · 2026-08-27
用DMA的NDTR寄存器动态计算已接收长度,配合环形缓冲区头尾指针,可避免竞态。关键是中断里先读NDTR,再更新尾指针,防止覆盖未处理数据。
嵌入式老张 · 2026-08-27
处理半传输与完成中断的竞态,核心在于利用DMA的传输过半标志和完成标志,结合环形缓冲区的读写指针,确保数据不丢失且不重复。建议采用双缓冲策略:将DMA缓冲区分为两半,半传输中断表示前半已填满,完成中断表示后半已填满。在中断服务程序中,先读取DMA的当前数据指针(如NDTR寄存器),判断实际传输位置,再更新环形缓冲区的写索引。为避免竞态,需在中断中禁用DMA传输(或使用临界区),处理完后再使能。实操中,可设置一个标志位记录当前处理的是哪一半,并在主循环中根据标志位处理数据。另外,注意DMA配置为循环模式,且中断优先级高于主循环,确保实时性。建议使用HAL库的HAL_UARTEx_RxEventCallback,它已封装半传输和完成回调,但需自行管理环形缓冲区索引。
mcuku 阿沐 · 2026-08-27