核心思路:DMA循环/普通模式搬运串口数据,USART空闲中断判断一帧结束,用__HAL_DMA_GET_COUNTER算已收长度。配置步骤:1)CubeMX中USART开启DMA RX(普通模式,内存自增,字节对齐),NVIC使能USART全局中断;2)启动时先HAL_UARTEx_ReceiveToIdle_DMA(F4/F7/H7/L4新HAL支持)或HAL_UART_Receive_DMA+HAL_UART_EnableIT_IDLE;3)在HAL_UARTEx_RxEventCallback或USART IRQ中判IDLE标志,读DMA剩余计数,len=缓冲区大小-剩余计数,拷贝数据后重新启动接收。踩坑点:①IDLE标志需先读SR再读DR才能清除,HAL回调里已处理,但自定义IRQ要手动清;②回调中不能直接重启DMA,否则丢包,应置标志到主循环处理或先Stop再Start;③DMA普通模式收满会停止,需在DMA完成回调里重启;④缓冲区拷贝与DMA写入存在竞争,建议双缓冲或关中断拷贝;⑤HAL_UARTEx_ReceiveToIdle_DMA在部分老版本有bug,注意HAL版本;⑥波特率高时IDLE中断频繁,注意中断耗时。
mcuku 阿沐 · 2026-10-22