STM32 使用 DMA 在 UART 空闲中断中如何避免半字对齐导致的数据错位?

· 1 浏览

回答(4)

实操建议:使用环形缓冲区(如`ring_buffer`)配合DMA,在空闲中断中只更新写索引,不直接操作数据,这样即使有半字错位,也能通过索引偏移修正,且不影响实时性。
硬件工程师阿杰 · 2026-08-27
注意:空闲中断中读取`DMA_GetFlagStatus`时,需先清除`DMA_FLAG_TC`和`DMA_FLAG_HT`标志,否则可能误判传输完成,导致长度计算错误。
码农小刘 · 2026-08-27
补充:检查DMA的FIFO设置,若启用FIFO且阈值设为HalfWord,可能强制对齐。建议禁用FIFO(`DMA_FIFOMode_Disable`)或设为Byte阈值,确保数据流不被拆分。
嵌入式老张 · 2026-08-27
在STM32的UART空闲中断中处理DMA数据时,半字对齐问题通常源于DMA传输的字节宽度与缓冲区对齐要求不匹配。核心解决思路是:确保DMA配置为字节(8位)模式,而非半字(16位)模式,因为UART数据本质是字节流。具体实操:1) 初始化DMA时,将外设数据宽度和内存数据宽度都设为Byte(`DMA_PeripheralDataSize_Byte`和`DMA_MemoryDataSize_Byte`),避免自动对齐到16位边界。2) 在空闲中断中,通过`__HAL_DMA_GET_COUNTER`获取剩余未传输字节数,计算已接收长度时使用`buffer_size - counter`,并确保缓冲区起始地址按4字节对齐(使用`__ALIGN_BEGIN`或`align(4)`修饰),防止因地址非对齐导致DMA硬件截断。3) 若必须使用半字模式(如外设寄存器宽度为16位),则需在接收后手动处理奇偶字节,通过`memcpy`或移位重组数据,但推荐直接改用字节模式,从根源消除错位。此外,建议在空闲中断中先关闭DMA(`HAL_DMA_Abort`),处理完数据后再重新配置,避免中断期间DMA继续写入导致竞态。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器