核心方案:采用“双缓冲+互斥锁”机制。将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