STM32 使用 DMA 接收不定长串口数据时,如何利用空闲中断避免丢帧并处理半字对齐问题?

· 2 浏览

回答(4)

建议用HAL库的HAL_UARTEx_ReceiveToIdle_DMA,它自动处理IDLE和半传输中断,但需注意回调中及时拷贝数据,避免覆盖。
STM32爱好者 · 2026-08-27
半字对齐问题也可通过修改DMA的PSIZE和MSIZE为8位,并让缓冲区地址4字节对齐,这样即使奇数长度也不会错位,且性能损失极小。
码农小飞 · 2026-08-27
补充:空闲中断判定帧结束,但若两帧间隔极短(小于1个字节时间),可能合并。可加超时定时器辅助,或使用DMA的传输完成中断做兜底。
嵌入式老周 · 2026-08-27
在STM32上使用DMA接收不定长串口数据时,核心思路是结合空闲中断(IDLE)来判定帧结束,避免依赖固定长度。具体做法:配置UART的DMA接收为循环模式,并启用IDLE中断。在IDLE中断服务函数中,先清除IDLE标志(读SR再读DR),然后计算当前DMA接收到的数据长度:len = 接收缓冲区大小 - DMA_CNDTR寄存器值。若len>0,则处理这批数据(如拷贝到环形缓冲区),并更新处理指针。关于半字对齐问题,主要出现在DMA配置为半字(16位)传输时,若数据长度是奇数,最后一个字节会错位。解决建议:优先使用字节(8位)模式接收串口,这是最稳妥的;若必须用半字(如配合某些外设),则需在IDLE中断中检查len的奇偶性,若为奇数,则手动调整最后一个字节的位置,或预留一个额外字节的缓冲区并确保DMA缓冲区大小是偶数。实操中,推荐使用双缓冲或环形缓冲,并在主循环中消费数据,避免在中断中做耗时操作。另外,注意STM32的IDLE中断在F1/F4系列中需在USART_IRQHandler中判断,而G0/L4等新系列支持更灵活的中断配置。
mcuku 阿沐 · 2026-08-27