1. 问题现象与初步排查
那天下午,我正在调试一个基于STM32F103的工业传感器采集项目。当我满怀信心地启动DMA串口传输时,示波器上的波形却让我心头一紧——数据只发送了前几个字节就戛然而止。更诡异的是,USART的TC(传输完成)标志位竟然被置位了,而DMA的传输完成中断却始终没有触发。
这种情况在32单片机开发中并不罕见,但背后的原因却可能千差万别。我立即展开了系统性排查:
- 首先用逻辑分析仪抓取USART_TX引脚信号,确认物理层是否有数据输出
- 检查DMA通道配置寄存器的CNDTR值,观察剩余传输计数是否递减
- 通过调试器查看DMA中断标志寄存器的状态位
- 对比不同时钟配置下的异常现象差异
关键发现:当使用72MHz主频时故障必现,而降频到48MHz后问题消失。这提示我们可能遇到了时钟同步问题。
2. DMA与串口的协同工作机制
要彻底理解这个故障,我们需要深入DMA控制器和USART外设的交互细节。以STM32F1系列为例,当配置USART1的TX使用DMA1通道4时,数据传输的完整链路是这样的:
- 用户程序设置DMA源地址(内存缓冲区)、目标地址(USART_DR寄存器)、传输量
- 使能DMA通道后,控制器开始将数据从内存搬运到USART数据寄存器
- USART的TXE(发送寄存器空)标志触发DMA请求
- DMA完成指定数量的传输后,触发传输完成中断
这里存在两个关键时序点:
- DMA传输速率受AHB总线时钟控制(通常与内核同频)
- USART的波特率时钟来自APB总线(通常为AHB的1/2分频)
当两者时钟不同步时,就可能出现DMA已经送完数据,但USART还未实际发送完毕的情况。此时如果过早关闭DMA或重置外设,就会导致传输截断。
3. 典型故障场景与解决方案
3.1 时钟配置不当
这是最常见的问题根源。以我的案例来说,系统时钟配置为72MHz,APB1总线时钟(USART1的时钟源)应为36MHz。但实际测量发现:
c复制// 错误配置示例:
RCC_PCLK1Config(RCC_HCLK_Div1); // 错误地将APB1设为72MHz
// 正确配置应为:
RCC_PCLK1Config(RCC_HCLK_Div2); // APB1最大允许
