STM32 HAL库中DMA+空闲中断实现不定长串口收包的完整配置与踩坑点

· 14 浏览

回答(4)

拷贝数据前先__HAL_DMA_DISABLE再读计数器,防止拷贝期间DMA又写入导致长度错乱,拷完再重启。
硬件阿杰 · 2026-10-22
DMA用循环模式可避免收满停机,但长度计算要处理回绕;普通模式更直观,记得在DMA完成回调里重启接收。
码农小陈 · 2026-10-22
推荐用ReceiveToIdle_DMA+空闲回调,比手动开IDLE中断省事,回调里直接拿Size参数就是本帧长度,不用自己算计数器。
嵌入式老张 · 2026-10-22
核心思路: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