STM32 使用 DMA 接收不定长串口数据时,如何避免空闲中断与数据竞争导致的丢包?

· 2 浏览

回答(4)

注意DMA传输完成中断和空闲中断可能同时触发,需在中断服务函数中判断标志位顺序,并利用DMA的传输完成标志来确认数据完整性。
硬件工程师阿强 · 2026-08-27
考虑使用硬件FIFO(如STM32F4的UART FIFO)配合DMA,减少中断频率。同时,用环形队列缓存应用层数据,避免中断处理耗时过长。
码农小飞 · 2026-08-27
可以改用空闲中断+单缓冲,但必须保证在空闲中断里快速拷贝数据,且DMA传输完成后立即重新配置,避免覆盖。适合数据量小的场景。
嵌入式老周 · 2026-08-27
核心思路是采用“DMA接收+空闲中断+双缓冲”机制,并配合临界区保护。首先,将DMA配置为循环模式,并启用两个大小相同的缓冲区(如BUFF_A和BUFF_B),通过DMA半传输/全传输中断切换当前写入缓冲区。空闲中断触发时,先关闭DMA传输(或暂停),读取当前DMA剩余计数(DMA_GetCurrDataCounter)确定有效数据长度,然后立即将数据拷贝到应用层队列,再重新开启DMA。为避免竞争,在空闲中断处理函数中,使用临界区(如__disable_irq/__enable_irq或互斥锁)保护对缓冲区索引和DMA控制寄存器的访问。同时,确保DMA中断优先级高于空闲中断,或统一在DMA中断中处理空闲标志。实操建议:使用HAL库时,可在HAL_UART_RxCpltCallback和HAL_UART_ErrorCallback中处理,但需注意HAL库的锁机制,必要时直接操作寄存器。测试时,用高速串口工具发送随机长度数据,验证无丢包。
mcuku 阿沐 · 2026-08-27