1. 为什么需要UART与DMA的组合方案
在嵌入式开发中,串口通信(UART)是最基础也最常用的外设之一。但传统轮询方式会占用大量CPU资源,而中断方式在高频数据传输时又容易造成数据丢失。这就是DMA(Direct Memory Access)技术大显身手的地方。
我曾在工业传感器数据采集项目中遇到过这样的问题:当传感器以115200波特率持续发送数据时,单纯使用中断接收会导致约3%的数据丢失。切换到DMA方案后,不仅实现了零丢包,CPU占用率还从78%降到了12%。这种提升在电池供电设备中尤为关键。
2. 硬件准备与环境搭建
2.1 开发板选型建议
虽然STM32全系支持UART+DMA,但不同型号的DMA控制器架构差异很大。以常见的STM32F1和F4系列为例:
- F1系列只有1个DMA控制器,7个通道共享带宽
- F4系列配备2个DMA控制器,每个控制器8个独立通道
如果项目需要同时处理多个高速数据流(比如同时接收GPS和传感器数据),建议选择F4或H7系列。我用F103C8T6做过测试,当两个UART同时以1Mbps传输时,DMA会出现约15%的带宽冲突。
2.2 软件工具链配置
除了必备的STM32CubeMX,强烈建议安装:
- VSCode + Cortex-Debug插件(比Keil更友好的调试体验)
- STM32CubeMonitor(实时监控串口流量)
- Termite(轻量级串口终端)
这里有个容易踩的坑:CubeMX生成的代码默认使用HAL库,但如果你之前用标准外设库(SPL)开发过项目,注意HAL库的中断优先级配置方式完全不同。我曾因此浪费两天时间排查为什么DMA传输不触发。
3. CubeMX工程配置详解
3.1 引脚分配与时钟树配置
在Pinout视图中启用USART1后,需要特别注意:
- TX/RX引脚可能被复用为其他功能(比如F103的PA9/PA10也是USB DM/DP)
- 高速通信时建议开启引脚的高速模式(GPIO_Speed)
时钟配置直接影响通信稳定性。以72MHz主频的F103为例:
- 在Clock Configuration中确保APB2总线时钟为72MHz(USART1挂载在此总线)
- 波特率计算公式为:APB2_CLK/(
