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

· 1 浏览

回答(4)

若总线负载高,可考虑使用FIFO模式(如USART的FIFO),配合DMA的突发传输,减少CPU干预,但需确认芯片支持。
硬件优化师 · 2026-08-27
建议在DMA传输完成中断中只置标志位,主循环中处理数据,减少中断嵌套风险。同时,用内存屏障(__DMB())确保数据可见性。
芯片级调试员 · 2026-08-27
可用环形队列替代双缓冲,通过读/写索引原子操作(如CAS)避免竞争,但需注意Cortex-M3/M4不支持硬件CAS,需关中断实现。
嵌入式老周 · 2026-08-27
核心方案:采用“双缓冲+互斥锁”机制。将DMA配置为循环模式,使用两个缓冲区交替接收,通过空闲中断(IDLE)判断一帧结束,切换当前写入缓冲区。在DMA传输完成中断中,仅更新写指针,不直接操作数据;在空闲中断中,锁定当前缓冲区,将数据拷贝到应用层后解锁。为避免总线竞争,确保DMA与外设时钟同步,且禁止在中断中调用阻塞函数(如printf)。数据错位主要源于DMA半传输/全传输中断与空闲中断的时序竞争,建议在空闲中断中先读取DMA的CNDTR寄存器,确认剩余字节数,再计算有效数据长度。实操建议:1)使用__disable_irq()/__enable_irq()保护缓冲区切换;2)将DMA优先级设为最高,但空闲中断优先级略低,避免丢失帧尾;3)若使用HAL库,注意HAL_UART_Receive_DMA的底层实现,必要时直接操作寄存器。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器