STM32 使用 DMA 与空闲中断接收不定长数据时,如何避免总线竞争与缓存覆盖?

· 1 浏览

回答(4)

考虑用环形缓冲区(如rt_ringbuffer)替代双缓冲,配合DMA循环模式,CPU按需读取,更灵活但需处理读写指针原子性。
硬件工程师阿强 · 2026-08-27
若用HAL库,注意在空闲中断中调用HAL_UART_DMAStop()停止DMA,再重新启动,否则可能因DMA未复位导致数据错位。
码农小飞 · 2026-08-27
建议开启DMA的FIFO模式并设置阈值,可减少总线占用冲突;同时用__disable_irq/__enable_irq保护缓冲区切换临界区,防止中断嵌套。
嵌入式老周 · 2026-08-27
核心思路是采用双缓冲(乒乓缓冲)配合DMA半传输/传输完成中断,而非仅依赖空闲中断。具体实操:1) 定义两个缓冲区buf1/buf2,DMA循环模式分别映射到两个缓冲区,启用DMA的HT(半传输)和TC(传输完成)中断,在中断中切换当前有效缓冲区并拷贝数据,避免CPU与DMA同时访问同一内存。2) 空闲中断只作为帧结束标志,不直接处理数据,而是置位标志位,由主循环或任务处理,减少中断内耗时。3) 关键点:在DMA中断中禁止再次触发相同中断(如清标志位),且使用volatile修饰共享变量;若使用RTOS,建议用消息队列传递缓冲区指针,避免锁竞争。4) 若总线竞争指I2C/SPI等外设,需确保DMA与外设时钟同步,并配置DMA的优先级高于外设中断,同时使用互斥信号量保护共享外设。缓存覆盖风险主要来自DMA写入与CPU读取不同步,双缓冲可彻底解决,但需注意DMA传输长度固定,空闲中断时可能未填满缓冲区,需记录实际接收长度。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器