GPIO与串口硬件原理:USART外设框图解析

做嵌入式开发这么多年,我见过不少工程师一上来就调串口,调不通就怀疑代码。其实很多时候,问题出在硬件理解上。你想想看,串口通信的本质是什么?就是两根线——TX发、RX收。但STM32的USART外设,远不止这么简单。

这一节,咱们把USART的硬件原理掰开揉碎了讲。搞懂了这些,以后串口出问题,你脑子里就能浮现出框图,定位故障会快很多。

USART外设框图核心模块

STM32F103的USART,说白了是一个完整的串行通信引擎。我习惯把它拆成四个部分来看:

  • 数据通路:发送移位寄存器 + 接收移位寄存器
  • 波特率发生器:决定通信速度
  • 控制逻辑:中断、DMA、状态标志
  • 引脚接口:TX/RX以及流控引脚

下面这张图,是我自己画的一个简化版框图,把关键模块和信号流向标出来了。

核心要点:USART的发送和接收是独立的硬件通道,可以全双工工作。发送数据从CPU写入DR寄存器,然后由移位寄存器逐位发出;接收数据由移位寄存器逐位收进来,再拼成完整字节存入DR。

STM32F103 USART 外设框图 CPU / 总线 数据寄存器 (DR) 发送移位寄存器 接收移位寄存器 波特率发生器 控制逻辑 TX 引脚 RX 引脚 关键说明 ① 发送和接收独立并行工作,支持全双工通信 ② 波特率发生器为发送和接收提供相同的移位时钟 ③ 控制逻辑管理中断、DMA请求、状态标志(TXE、RXNE等)

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位,逻辑高电平

我画了个时序图,方便你理解:

USART 数据帧格式(8位数据 + 无校验 + 1位停止) 空闲 (高电平) 起始 (低) D0 D1 D2 D3 D4 D5 D6 D7 停止 (高) 一帧数据 = 1位起始 + 8位数据 + 1位停止 = 10位。如果使能校验位,则数据位后插入1位校验。

关键参数配置:在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和分频系数决定,计算时要确认时钟源
  • 数据帧格式必须收发一致,否则通信失败
  • 硬件流控在高速或远距离通信时很有用,但配置要完整

搞懂了这些,后面咱们调代码、定位故障,你心里就有底了。