如何在不使用RTOS的情况下用状态机优雅地管理多个UART外设的DMA接收与超时处理

· 2 浏览

回答(4)

如果UART数量多,可考虑用DMA的通道优先级+中断嵌套,但无RTOS下建议所有中断处理保持极短,只置标志位,实际解析放主循环,避免中断风暴。
硬件控小李 · 2026-08-27
DMA空闲中断是精髓,但注意STM32的IDLE标志需软件清零,且要在中断中读取SR和DR才能正确触发,否则会漏帧。
码农阿杰 · 2026-08-27
建议将状态机做成表驱动(函数指针数组),每个UART实例化一个结构体(含状态、缓冲区指针、超时计数),这样扩展新UART只需增加结构体实例,代码复用率高。
嵌入式老周 · 2026-08-27
核心思路:用分层状态机+环形缓冲区+DMA空闲中断(IDLE)实现无RTOS的多UART管理。每个UART维护独立的状态机(IDLE→RECEIVING→PROCESSING→IDLE),状态迁移由DMA传输完成中断和IDLE中断驱动。具体做法:1) 为每个UART分配DMA通道和环形缓冲区,DMA接收数据直接写入缓冲区,不触发CPU中断(除IDLE和半满/全满);2) 配置UART的IDLE中断,当总线空闲时触发,此时读取DMA剩余计数,计算本次接收长度,将数据从环形缓冲区取出放入协议解析队列;3) 主循环中统一轮询所有UART的状态机,处理超时(如IDLE后500ms无新数据则强制结束帧)和协议解析。关键优化:用位图记录各UART的待处理事件,主循环一次遍历即可,避免逐UART轮询开销。超时处理建议用硬件定时器(如SysTick)产生1ms时基,每个UART维护一个超时计数器,在状态机中递减。注意DMA的循环模式(Circular)可避免缓冲区溢出,但需处理半满中断以搬运数据。
mcuku 阿沐 · 2026-08-27