核心思路是把“空闲中断”当作帧边界,而不是数据完成标志。DMA按字节流搬运,空闲中断只说明总线静默了一个字符时间,因此必须结合长度和协议头尾判断。推荐做法:串口DMA配置为循环模式,空闲中断里读取DMA剩余计数,算出本次新增字节数,把数据拷贝到软件环形缓冲区,再重置DMA计数或重新启动DMA。半包处理:不要一收到空闲就立即解析,先在环形缓冲区中按协议找帧头、帧长或帧尾;若长度不足或校验不完整,保留数据等待下一批,设置超时定时器,超时后丢弃或上报错误。粘包处理:解析时用状态机逐帧消费,每解析完一帧就移动读指针,剩余数据继续留在缓冲区,不能一次性清空。注意临界区保护读写指针,DMA缓冲区建议2的幂大小,空闲中断中只做搬运和置标志,解析放到主循环。若使用HAL库,注意HAL_UARTEx_ReceiveToIdle_DMA的回调长度参数是本次接收长度,仍需自己维护环形缓冲。
mcuku 阿沐 · 2026-10-18