STM32 使用 DMA 接收不定长串口数据时,如何通过空闲中断与环形缓冲区协同避免数据覆盖?

· 2 浏览

回答(4)

更稳妥方案:采用空闲中断+DMA+RTOS消息队列,中断中只做数据搬移和队列写入,业务线程从队列读取,彻底解耦。注意关中断保护环形索引。
硬件工程师阿杰 · 2026-08-27
注意:STM32的IDLE中断在接收完一帧后需软件清除标志,且DMA的NDTR是递减的,计算长度用BufferSize-NDTR。若使用HAL库,可重写UART_IdleCpltCallback。
码农小刘 · 2026-08-27
补充:空闲中断只标志一帧结束,若连续接收无空闲,需依赖DMA半满/全满中断及时搬移数据,否则环形缓冲区会覆盖。建议将DMA缓冲区设为2的幂次,便于索引取模。
嵌入式老周 · 2026-08-27
核心思路:利用STM32的IDLE空闲中断配合DMA循环模式(Circular Mode),将接收缓冲区设计为环形结构。配置DMA接收长度等于缓冲区大小,启用DMA传输完成中断(半传输/全传输)和USART空闲中断。当空闲中断触发时,读取DMA当前数据指针(NDTR寄存器)计算本次有效数据长度,并更新环形缓冲区的写索引;DMA继续在后台循环接收,不停止。为避免覆盖,需在应用层及时消费数据,并确保环形缓冲区容量大于DMA缓冲区。实操建议:1) 使用双缓冲(乒乓)或环形索引,在空闲中断中拷贝数据到应用层队列;2) 注意DMA半传输中断用于处理缓冲区前半部分,防止数据覆盖;3) 若数据量大,可结合串口超时定时器兜底。
mcuku 阿沐 · 2026-08-27