STM32 使用 DMA 与环形缓冲区配合时,如何精确处理半传输中断与传输完成中断的时序竞争?

· 2 浏览

回答(4)

如果允许,直接改用DMA双缓冲模式(如F4/F7系列),硬件自动切换缓冲区并触发中断,无需手动管理半/全传输,代码简洁且无竞争。
硬件控阿杰 · 2026-08-27
注意DMA的NDTR寄存器是递减的,读取时要加临界区保护,否则可能读到中间值。可用__disable_irq()包住读取,再恢复,成本很低。
码农小飞 · 2026-08-27
建议用状态机管理缓冲区:定义‘前半区可读’和‘后半区可读’两个标志位,在HT和TC中置位,主循环轮询处理,避免中断内做耗时操作,天然规避竞争。
嵌入式老周 · 2026-08-27
核心思路是让DMA的传输长度设为环形缓冲区的一半,利用半传输中断(HT)和传输完成中断(TC)分别标记前后半区,从而避免读写指针竞争。具体做法:初始化时设置DMA为循环模式(Circular),传输数据量设为缓冲区大小的一半(例如缓冲区256字节,DMA传输128字节)。当HT触发时,CPU可安全处理前半区(0-127);TC触发时处理后半区(128-255)。关键时序竞争点在于:若CPU在HT中断中处理数据时,DMA已写入后半区并再次触发TC,此时需保证中断优先级和临界区保护。实操建议:1)在中断服务函数中立即将DMA缓冲区的读写指针更新为原子操作(如关中断或使用临界区);2)将HT和TC中断优先级设为相同且高于其他外设,避免嵌套;3)在TC中断中检查DMA的当前传输计数(NDTR),若已回绕到前半区,则说明TC处理滞后,需合并处理。更稳妥的做法是使用双缓冲模式(若STM32支持),硬件自动切换,彻底消除竞争。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器