GPIO与串口硬件原理:USART外设框图解析
做嵌入式开发这么多年,我见过不少工程师一上来就调串口,调不通就怀疑代码。其实很多时候,问题出在硬件理解上。你想想看,串口通信的本质是什么?就是两根线——TX发、RX收。但STM32的USART外设,远不止这么简单。
这一节,咱们把USART的硬件原理掰开揉碎了讲。搞懂了这些,以后串口出问题,你脑子里就能浮现出框图,定位故障会快很多。
USART外设框图核心模块
STM32F103的USART,说白了是一个完整的串行通信引擎。我习惯把它拆成四个部分来看:
- 数据通路:发送移位寄存器 + 接收移位寄存器
- 波特率发生器:决定通信速度
- 控制逻辑:中断、DMA、状态标志
- 引脚接口:TX/RX以及流控引脚
下面这张图,是我自己画的一个简化版框图,把关键模块和信号流向标出来了。
核心要点:USART的发送和接收是独立的硬件通道,可以全双工工作。发送数据从CPU写入DR寄存器,然后由移位寄存器逐位发出;接收数据由移位寄存器逐位收进来,再拼成完整字节存入DR。
TX/RX引脚功能与复用
STM32的USART引脚,不是随便一个GPIO就能用的。每个USART外设都有固定的引脚映射。我刚开始做项目时,就犯过这个错——把TX接到一个不支持USART功能的引脚上,调了半天没反应。
以USART1为例,它的引脚是固定的:
| USART外设 | TX引脚 | RX引脚 | 备注 |
|---|---|---|---|
| USART1 | PA9 (AF推挽输出) | PA10 (浮空输入) | APB2总线,频率最高 |
| USART2 | PA2 (AF推挽输出) | PA3 (浮空输入) | APB1总线 |
| USART3 | PB10 (AF推挽输出) | PB11 (浮空输入) | APB1总线 |
我曾经踩过的坑:有一次我把USART2的TX配置成了推挽输出,但忘了配置为复用功能(AF)。结果TX引脚一直输出高电平,数据根本发不出去。记住:串口引脚必须配置为复用推挽输出(TX)和浮空输入(RX),不是普通的GPIO模式。
波特率发生器原理
波特率,说白了就是每秒传输的位数。STM32的波特率发生器,本质上是一个分频器。它从外设时钟(PCLK)出发,经过分频得到移位时钟。
计算公式很简单:
波特率 = PCLK / (16 × USARTDIV)
其中 USARTDIV 是一个16位的分频系数
存放在 BRR 寄存器中
举个例子,如果PCLK=72MHz,想要115200波特率:
USARTDIV = 72000000 / (16 × 115200) = 39.0625
整数部分 = 39 → 存入 BRR[15:4]
小数部分 = 0.0625 × 16 = 1 → 存入 BRR[3:0]
BRR = (39 << 4) | 1 = 0x0271
个人习惯:我一般直接用HAL库的 HAL_UART_Init(),它会自动计算BRR值。但调试时如果发现波特率不对,我会手动算一遍,确认时钟源和分频系数是否正确。尤其是当你用了外部晶振或者PLL倍频时,PCLK的值很容易搞错。
数据帧格式
串口通信的数据帧,就像一列火车。每一帧由几个部分组成:
- 起始位:1位,逻辑低电平。告诉接收端“准备收数据”
- 数据位:8位或9位,低位在前
- 校验位:可选,奇校验或偶校验
- 停止位:0.5、1、1.5或2位,逻辑高电平
我画了个时序图,方便你理解:
关键参数配置:在CubeMX中配置USART时,你需要选择:
- 数据位长度:8位(最常用)或9位
- 校验方式:无校验、奇校验、偶校验
- 停止位位数:1位(最常用)、0.5位、1.5位、2位
发送方和接收方的这些参数必须完全一致,否则数据就会错乱。
硬件流控制(RTS/CTS)
硬件流控制,说白了就是让接收方告诉发送方“我准备好了,你可以发了”或者“我忙不过来,你先停一下”。STM32的USART支持两种硬件流控信号:
- RTS (Request To Send):输出信号,告诉对方“我可以接收数据”
- CTS (Clear To Send):输入信号,对方告诉本机“你可以发送数据”
我个人的经验是,大部分场景用不到硬件流控。但如果你在做高速通信(比如460800波特率以上),或者通信距离较远,硬件流控就很有用了。它能防止接收缓冲区溢出。
| 流控模式 | RTS引脚 | CTS引脚 | 适用场景 |
|---|---|---|---|
| 无流控 | 未使用 | 未使用 | 短距离、低速、简单通信 |
| 仅RTS | 输出 | 未使用 | 接收方控制发送方 |
| 仅CTS | 未使用 | 输入 | 发送方受控于接收方 |
| 全流控 | 输出 | 输入 | 双向流量控制 |
我曾经踩过的坑:有一次调试一个GPS模块,模块要求硬件流控。我配置了USART的RTS/CTS,但忘了把对应的GPIO引脚配置为复用功能。结果RTS引脚一直输出无效电平,GPS模块收不到数据。后来用示波器一看,RTS引脚波形不对。嗯,从那以后我每次配置流控,都会先检查引脚复用配置。
小结
这一节的内容,说白了就是让你对USART的硬件有一个整体的认识。记住几个关键点:
- TX/RX引脚必须配置为复用功能,不是普通GPIO
- 波特率由PCLK和分频系数决定,计算时要确认时钟源
- 数据帧格式必须收发一致,否则通信失败
- 硬件流控在高速或远距离通信时很有用,但配置要完整
搞懂了这些,后面咱们调代码、定位故障,你心里就有底了。