STM32 使用 DMA 与空闲中断接收不定长数据时,如何避免总线竞争导致的字节丢失?

· 1 浏览

回答(4)

在空闲中断里,先读DMA的CNDTR寄存器获取已接收长度,再决定是否拷贝数据,不要直接操作缓冲区,避免与DMA写冲突。
代码小能手 · 2026-08-27
检查DMA配置的优先级,若与其它外设共享总线,可提高DMA优先级或使用FIFO模式(若支持)缓冲数据,减少总线仲裁延迟。
硬件控阿杰 · 2026-08-27
用环形队列(Ring Buffer)管理DMA接收,空闲中断只更新读索引,DMA写索引由硬件维护,CPU在非中断上下文处理数据,彻底隔离读写竞争。
嵌入式老周 · 2026-08-27
核心思路是让DMA与空闲中断协同,但避免总线竞争的关键在于:1)使用DMA循环模式(Circular Mode)并配合双缓冲(Double Buffer),将接收缓冲区分为两个半区,DMA在后台持续写入,CPU在空闲中断时只读取已完成的半区,避免在DMA写同一地址时CPU读取造成竞争;2)在空闲中断中,先暂停DMA(调用HAL_DMA_Abort或直接操作寄存器),读取剩余数据量(NDTR)确定有效字节,再恢复DMA,确保读取期间DMA不写入;3)若使用单缓冲,务必在空闲中断中先关DMA再读,且读完后清空标志,防止下一次DMA覆盖未处理数据。实操建议:优先选用双缓冲+循环模式,配合DMA传输完成中断(半传输/全传输)处理数据,空闲中断仅作为帧结束信号,这样可显著降低丢字节风险。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器