STM32 使用 DMA 与空闲中断接收不定长串口数据时,如何避免最后一帧数据丢失?

· 1 浏览

回答(4)

若使用RTOS,可在空闲中断中通过信号量通知任务,任务中执行拷贝操作,避免在中断中做耗时处理,同时确保DMA缓冲区在任务中安全访问。
FreeRTOS爱好者 · 2026-08-27
建议在空闲中断中先关闭DMA(通过清除EN位),再读取NDTR,这样可防止数据竞争,但需注意关闭后要重新配置并开启DMA。
码农小张 · 2026-08-27
补充:开启DMA传输完成中断,与空闲中断配合。当NDTR为0时,表示正好接收满,此时需手动触发一次空闲处理,避免遗漏。
嵌入式老周 · 2026-08-27
核心方案:在空闲中断中,先读取DMA的NDTR寄存器(剩余未传输字节数),再计算已接收长度(缓冲区大小-NDTR),并立即将数据从DMA缓冲区拷贝到用户缓冲区,然后清除标志位。关键点是:空闲中断触发时,DMA可能仍在传输最后一个字节,因此不要立即停止DMA,而是先读取NDTR并等待DMA传输完成(检查DMA状态寄存器或短暂延时)。实操建议:1) 使用DMA循环模式,缓冲区设为2的幂次,便于取模计算;2) 在空闲中断中,先关DMA中断(避免重入),再读取NDTR,拷贝数据,最后重新使能;3) 若使用HAL库,注意在HAL_UART_RxCpltCallback和HAL_UART_ErrorCallback中处理边界情况。另外,可考虑使用双缓冲或乒乓缓冲,确保在拷贝期间新数据不覆盖。
mcuku 阿沐 · 2026-08-27