STM32 使用 DMA 在 UART 空闲中断中接收不定长数据时,如何避免因总线冲突导致的半字对齐错误?

· 1 浏览

回答(4)

在空闲中断中,用volatile修饰缓冲区指针,并插入内存屏障(如__DMB()),防止编译器或CPU乱序访问,确保数据一致性。
码农阿杰 · 2026-08-27
检查时钟树,确保DMA和UART的时钟源同步,若使用HSE或PLL,可降低总线频率差异,减少因时钟抖动导致的采样错位。
芯海行者 · 2026-08-27
用双缓冲(Ping-Pong)配合DMA传输完成中断,避免在空闲中断中直接操作DMA,让数据在后台无缝切换,彻底消除冲突窗口。
嵌入式老张 · 2026-08-27
在UART空闲中断中接收不定长数据时,半字对齐错误通常源于DMA传输与CPU访问外设寄存器或内存的时序冲突,尤其在STM32的AHB总线矩阵上,DMA和CPU可能同时访问SRAM或外设。核心解决策略:1) 启用DMA的循环模式(Circular Mode)并配合空闲中断,确保DMA始终在内存中连续写入,避免因停止/重启DMA造成的边界错位;2) 在空闲中断中,先读取DMA的CNDTR寄存器获取剩余数据量,再计算实际接收长度,但必须确保读取CNDTR时DMA未在传输(可短暂禁用DMA或使用DMA的传输完成中断同步);3) 若使用半字(16位)数据,务必保证DMA配置的数据宽度(PSIZE/MSIZE)与外设寄存器(如UART->DR)一致,且内存缓冲区按2字节对齐(使用__attribute__((aligned(4)))),否则总线拆分访问会导致半字错误;4) 推荐使用DMA的FIFO模式(若芯片支持),设置阈值(如Half/Full)缓冲数据,减少总线竞争窗口。实操建议:在空闲中断中,先关闭DMA(DMA_Cmd(DMAx_Channelx, DISABLE)),读取CNDTR,处理数据,再重新配置并启动DMA,同时用临界区保护(如__disable_irq)防止中断嵌套。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器