一、六个标准问题
① 挂哪条总线
USART1 挂 APB2(72MHz)。
回顾:F103 有三个 USART(大容量 ZET6 有 USART1/2/3 + UART4/5),总线分配不同:
| 外设 | 总线 | 时钟频率 | 本板用途 |
|---|---|---|---|
| USART1 | APB2 | 72MHz | CH340K 串口(PA9/PA10) |
| USART2 | APB1 | 36MHz | 扩展(PA2/PA3) |
| USART3 | APB1 | 36MHz | 扩展(PB10/PB11) |
| UART4/5 | APB1 | 36MHz | 扩展 |
USART1 是唯一挂在 APB2 的串口,时钟直接 72MHz,不需要倍频补偿,波特率计算最精确。这也是为什么调试串口首选 USART1。
② 时钟来源与特殊倍频
HSE 8MHz → PLL×9 → SYSCLK 72MHz
→ HCLK 72MHz
→ PCLK2 72MHz(APB2 不分频)
→ USART1 72MHz
USART1 时钟 = PCLK2 = 72MHz,无倍频、无分频,直接用。
对比:USART2/3/4/5 挂 APB1,PCLK1=36MHz,波特率计算时基准时钟是 36MHz。
③ 门控开关
USART1 的时钟使能位在 RCC_APB2ENR 的 bit14(USART1EN):
RCC_APB2ENR |= RCC_APB2ENR_USART1EN; // 开 USART1 时钟
同时,USART1 用 PA9/PA10,GPIOA 也要开:
RCC_APB2ENR |= RCC_APB2ENR_IOPAEN; // 开 GPIOA 时钟
配电箱比喻:
总闸 SYSCLK 72MHz
└─ 分闸 APB2ENR(72MHz 母线)
├─ IOPAEN → GPIOA 房间(PA9/PA10 引脚)
└─ USART1EN → USART1 房间(波特率发生器/收发器)
两个开关都要开,缺一不可:GPIO 负责引脚电平物理输出,USART 负责协议帧时序。
④ CubeMX 中对应配置
CubeMX 中配置 USART1 非常简单,大部分参数 CubeMX 自动处理:
| 配置项 | CubeMX 位置 | 是否可见 |
|---|---|---|
| USART1 时钟使能 | 勾选 USART1 → 自动开 | 隐藏,自动生成 |
| GPIOA 时钟使能 | 选 PA9/PA10 → 自动开 | 隐藏,自动生成 |
| PA9 = USART1_TX | Connectivity → USART1 | 可见 |
| PA10 = USART1_RX | Connectivity → USART1 | 可见 |
| 波特率/字长/停止位/校验 | Parameter Settings | 可见 |
注意:GPIOA 的时钟使能(IOPAEN)在 CubeMX 界面无可见开关,选了 PA9/PA10 后自动推断生成。这和你学 GPIO 时 IOPBEN 不可见是同样的道理。
⑤ 寄存器参数(USART 核心寄存器)
USART 外设核心寄存器就几个,理解这 5 个就够:
| 寄存器 | 作用 | 关键位 |
|---|---|---|
| USART_SR(状态寄存器) | 查状态 | TXE(发送缓冲空)、TC(发送完成)、RXNE(接收缓冲非空) |
| USART_DR(数据寄存器) | 读写数据 | 写→发送、读→接收,只有低8位有效 |
| USART_BRR(波特率寄存器) | 设波特率 | DIV_Mantissa + DIV_Fraction = 分频值 |
| USART_CR1(控制寄存器1) | 总开关 | UE(USART使能)、TE(发送使能)、RE(接收使能)、RXNEIE(接收中断使能) |
| USART_CR2(控制寄存器2) | 帧参数 | STOP[1:0](停止位)、CLKEN(同步时钟) |
波特率计算公式(异步模式):
波特率 = fPCLK / (16 × DIV)
其中 fPCLK = 72MHz(USART1),DIV = BRR 里的分频值(整数+小数,共12位整数+4位小数)。
以 115200 为例:
DIV = 72000000 / (16 × 115200) = 39.0625
整数部分 = 39 = 0x27
小数部分 = 0.0625 × 16 = 1 = 0x1
BRR = 0x271
CubeMX 填 115200 后自动算好写进 BRR,不用手算。但原理要知道。
⑥ 硬件行为(数据从发送到接收的完整链路)
发送链路(STM32 → 电脑):
写 DR 寄存器
→ 移位寄存器逐位输出
→ TX 引脚(PA9) 按协议帧输出 TTL 电平
→ CH340K 收到 TTL 信号,转成 USB 协议
→ USB 线传到电脑
→ 电脑端 CH340 驱动转为虚拟 COM 口
→ 串口助手软件显示数据
接收链路(电脑 → STM32):
串口助手发送数据
→ 电脑 USB → CH340K
→ CH340K 转 TTL → PA10(RX) 引脚
→ USART1 接收移位寄存器逐位采样
→ 收满一帧 → 数据写入 DR
→ 置 RXNE 标志 → 可读 DR 获取数据
二、CH340K 连接电路(TX/RX 交叉)
这是最容易接错的地方,务必记住:TX→RX,RX→TX,交叉连接。
STM32 CH340K
PA9 (USART1_TX) ──→ RXD
PA10 (USART1_RX) ←── TXD
GND ─────────────── GND (共地!必须接)
为什么必须交叉?TX 是输出,RX 是输入。如果 TX→TX,两个输出对冲,谁也收不到数据。就像打电话,你的嘴(TX)要对对方的耳朵(RX),不可能嘴对嘴。
你开发板上 CH340K 和 STM32 已经在 PCB 上固定连好了(PA9→CH340 RX、PA10→CH340 TX、共地),用一根 USB 线接电脑即可,不用飞线。
三、完整挂载使能总链路图
把六层串起来,这是整个 USART1 的全景:
Cortex-M3 内核
│
▼ SYSCLK = 72MHz(HSE 8MHz × PLL9)
│
▼ HCLK = 72MHz
│
▼ PCLK2 = 72MHz(APB2,不分频)
│
├── RCC_APB2ENR.IOPAEN ───→ GPIOA 使能
│ ├── PA9 → 复用推挽输出(USART1_TX)
│ └── PA10 → 浮空/上拉输入(USART1_RX)
│
└── RCC_APB2ENR.USART1EN ─→ USART1 使能
├── BRR = 0x271(115200bps)
├── CR1 = UE|TE|RE(使能+收发)
├── SR.TXE → 发送缓冲空,可写 DR
├── SR.RXNE → 接收缓冲有数据,可读 DR
└── DR → 读写数据
│
▼
PA9/PA10 引脚电平变化
│
▼
CH340K(TTL↔USB)
│
▼
电脑 USB → 虚拟 COM → 串口助手
四、PA9/PA10 的 GPIO 模式
USART 用的是复用功能(AF),GPIO 模式和普通 IO 不同:
| 引脚 | 功能 | GPIO 模式 | 说明 |
|---|---|---|---|
| PA9 | USART1_TX | 复用推挽输出 | 数据由 USART 外设驱动输出,不由 GPIO_ODR 驱动 |
| PA10 | USART1_RX | 浮空输入/上拉输入 | 接收由 USART 外设采样,GPIO 只需配置为输入 |
关键理解:一旦开启 USART 的 TE(发送使能),PA9 的输出控制权就从 GPIO 模块移交给了 USART 外设,此时写 GPIO_ODR 无效,数据要写 USART_DR 才会从 PA9 发出。这就是"复用"的含义——引脚被外设"借用"了。
CubeMX 中你只需选 PA9 = USART1_TX、PA10 = USART1_RX,GPIO 模式自动配好,不用手动设。