“控制硬件”的本质就是“读写寄存器”。我们可以把 STM32 想象成一个巨大的控制中心,而寄存器(Register)就是控制中心面板上密密麻麻的旋钮和开关。
1. 什么是寄存器
从物理上看,寄存器就是一小块极速存储单元,通常是 32 位(因为 STM32 是 32 位机),每一位(Bit)就是一个开关。
- 它的位置: 它们就在外设(如 GPIO、定时器、串口)的内部。
- 它的门牌号: 就像 [[ZZZ-02-Flash和SRAM]] 中写的,每个寄存器都有一个唯一的内存地址。
- 它的作用:
- 配置寄存器: 像“设置菜单”。比如:设置这个引脚是做输入还是输出?
- 数据寄存器: 像“数据通道”。比如:我想让引脚输出高电平,就往这里写 1。
- 状态寄存器: 像“仪表盘”。比如:串口收到数据了吗?看看这个寄存器的某一位是不是变成了 1。
案例说明
当你执行 *(uint32_t *)0x4001080C = 0x01; 时,发生了以下神奇的事情:
- 软件层面: 你把内存地址
0x4001080C对应的那个 32 位“小盒子”里的第 0 位改成了1。 - 硬件逻辑层面: 这个寄存器物理上连接着一堆逻辑电路(锁存器、MOS 管等)。硬件电路检测到寄存器这一位变成了
1。 - 电气层面: 内部的 MOS 管导通,将芯片内部的 VDD(通常是 3.3V) 电源连接到那个物理引脚(Pin)上。
- 结果: 引脚上出现了 3.3V 的电压,也就是我们说的“高电平”。
所以,你控制的是寄存器里的“逻辑电平(0 和 1)”,硬件电路根据你的逻辑,输出真实的“物理电平(0V 和 3.3V)”。
寄存器编程 vs. 库函数编程
虽然底层全是寄存器,但现在的开发者很少直接写 0x4001080C 这种魔术数字了。
方式 A:寄存器操作(硬核)
|
|
- 优点: 速度极快,代码体积最小。
- 缺点: 极难阅读,翻手册翻到头秃。
方式 B:HAL 库操作(主流)
|
|
- 优点: 像人类语言,好理解,换个芯片也好移植。
- 本质:
HAL_GPIO_WritePin这个函数的内部,最终还是去操作了那几个寄存器地址。
总结
- 引脚(Pin): 工厂的出货口。
- 寄存器(Register): 控制出货口的开关闸门。
- 地址(Address): 找到那个闸门的唯一路径。
- 库函数(Library): 开关的操作手册和自动机械臂。
进阶思考
既然一切都是寄存器,那么“串口发送数据”是怎么回事呢? 其实就是:
- 检查“状态寄存器”,看上一个字发完没。
- 如果发完了,把你要发的字符丢进“数据寄存器”。
- 芯片内部的硬件电路会自动把这个寄存器里的 8 位数据变成一串高低电平,从引脚“嗖”地射出去。