STM32 串口 + DMA(RX/TX)在不知道要接多少字节的情况下,用 DMA 长期稳定地接收数据并通知上层处理

 

stm32-usart-uart-dma-rx-tx 是一个示例 / 工具集合,演示了如何把 STM32 的 UART(USART/LPUART)和 DMA 结合起来,高效做接收(RX)和发送(TX)。重点是:在你不知道要接多少字节的情况下,还能用 DMA 长期稳定地接收数据并通知上层处理。

它能解决什么痛点

  • • CPU 被串口中断/轮询反复打断,系统性能下降 → 用 DMA 把数据搬到内存,CPU 去做别的事。

  • • 接收长度未知,传统 DMA 要提前写好长度导致不行 → 用循环模式 + IDLE/RTO + HT/TC 组合来识别“包”边界。

  • • 串口速率高(>1Mbps)或者有大数据爆发时,普通中断/轮询容易丢数据 → DMA 高速搬移,减小丢包风险。

  • • 发送大块数据会卡住 CPU → 用 DMA TX(normal 模式),发送过程中 CPU 不阻塞。

核心思想

  • • RX:把 DMA 配成 circular(环形)模式,让它不停往一个固定大小的 buffer 写;再通过三个事件来知道什么时候处理数据:

    • • HT(半传中断)、TC(传完中断)是 DMA 的;

    • • IDLE(空闲线)或 RTO(接收超时)是 UART 的。
      三者结合,可以在不知长度的情况下,及时安全地把已收到的数据交给应用处理,避免覆盖未处理数据。

  • • TX:把要发的内存地址和长度写进 DMA,normal 模式,DMA 传完发一个 TC,CPU 就知道可以继续发下一块了。很像把搬运工交给硬件。

安装 / 克隆 / 运行(一步到位)

  • • 克隆仓库(包含子模块):

    • • git clone –recurse-submodules https://github.com/MaJerle/stm32-usart-dma-rx-tx

  • • 用 STM32CubeIDE 打开 projects 目录下的对应例程(仓库里覆盖了多个 STM32 家族示例)。

  • • 例程基于 LL(Low-Level)驱动,配置:115200/8N1、DMA RX 为 circular 开启 HT/TC、DMA TX 为 normal。

  • • 按照 README 里说明选对板子和 DMA 通道、修改 pin 配置后直接编译烧写。

优点 / 好处

特性

好处

DMA RX(circular)

极低 CPU 占用,能连续接收高速数据

DMA TX(normal)

发送时不阻塞主线程,适合大数据量/日志输出

IDLE + HT/TC 组合

在长度未知时也能可靠切割包并及时处理

LL 驱动示例

易于理解底层机制,便于移植与修改

支持多家族

F1/F4/G0/G4/L4/H7/U5 等示例,适配广泛硬件

缺点 / 限制

  • • 需要你理解 NVIC 优先级,错误设置会导致数据乱读。

  • • IDLE/RTO 并非所有 STM32 都有(有些芯片不能用 IDLE,需要轮询)。

  • • 如果处理函数写在中断里,太慢会影响系统实时性 —— 推荐把中断只做通知。

  • • buffer 大小、baud、处理速度三者需要平衡,设计不当会丢包。

总结
如果你想在 STM32 上做稳定且高性能的串口收发,把 UART 和 DMA 配合起来是必经之路;关键在于用 circular buffer + HT/TC + IDLE/RTO 的“组合拳”,并做好中断优先级和数据处理策略。MaJerle 的仓库给了完整且可跑的参考例程,直接拿来改就是生产力。

项目地址:https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx

 

发表评论