目录
- 前言
- 一、MCU内部架构与时钟树的深度打通
-
- [1.1 从"两张皮"到"合二为一"的认知跨越](#1.1 从“两张皮”到“合二为一”的认知跨越)
- [1.2 官方资料的局限性与自建理解模型](#1.2 官方资料的局限性与自建理解模型)
- [1.3 总线的本质:三类信号线的集合](#1.3 总线的本质:三类信号线的集合)
- [1.4 寄存器统一编址与CPU访问机制](#1.4 寄存器统一编址与CPU访问机制)
- [1.5 设备协同与时钟同步的关键作用](#1.5 设备协同与时钟同步的关键作用)
- 二、时钟树如何驱动整个MCU
-
- [2.1 时钟树与总线时钟线的物理映射](#2.1 时钟树与总线时钟线的物理映射)
- [三、MCU 寄存器配置的本质与存储单元原理](#三、MCU 寄存器配置的本质与存储单元原理)
-
- [3.1 配置的本质:从 CPU 到外设的数据搬运](#3.1 配置的本质:从 CPU 到外设的数据搬运)
- [3.2 存储单元的工作机制:写入、读取与保持](#3.2 存储单元的工作机制:写入、读取与保持)
- [3.3 多位寄存器的构建:并行锁存](#3.3 多位寄存器的构建:并行锁存)
- 四、时钟信号与总线传输的协同机制
-
- [4.1 朴素的数据传输模型](#4.1 朴素的数据传输模型)
- [4.2 时钟的核心作用:同步控制的开关](#4.2 时钟的核心作用:同步控制的开关)
- [4.3 关于"同步"的深度理解](#4.3 关于“同步”的深度理解)
- [五、MCU 内部架构全景:时钟树与总线的打通](#五、MCU 内部架构全景:时钟树与总线的打通)
-
- [5.1 从时钟源到 Cortex-M3 内核](#5.1 从时钟源到 Cortex-M3 内核)
- [5.2 数据流动的完整路径](#5.2 数据流动的完整路径)
- [5.3 一次完整的写操作复盘](#5.3 一次完整的写操作复盘)
- 结语


🎬 云泽Q :个人主页
🔥 专栏传送入口 : 《C语言》《数据结构》《C++》《Linux》《蓝桥杯系列》《笔试算法》《AI赋能》《STM32》《Python》
⛺️遇见安然遇见你,不负代码不负卿~
前言
大家好啊,我是云泽Q,欢迎阅读我的文章,一名热爱计算机技术的在校大学生,喜欢在课余时间做一些计算机技术的总结性文章,希望我的文章能为你解答困惑~
一、MCU内部架构与时钟树的深度打通
1.1 从"两张皮"到"合二为一"的认知跨越
在之前的文章中,我们已经把时钟树的第一部分讲完了。这里要再强调一下,现阶段我们只关心时钟树的第一部分,其他部分等把第一部分用得特别熟之后,后续在理解上直接拿过来用就能理解了。现在虽然第一部分理解了,但还存在一个核心痛点:感觉上还是不够通透。


这就好比MCU内部有自己的结构图,时钟树也有自己的图,这两张图像是"两张皮",谁也不挨着谁。如果非要问外部输出对应的时钟信号是如何输出到不同平台上的,虽然能勉强理解,写代码也能勉强去写,但就是缺乏一种"通透感"。所以,我们需要再往前走一步,做一下时钟树与总线设备结构的打通,也就是把这两张图合二为一。
1.2 官方资料的局限性与自建理解模型
意法半导体(ST)的MCU确实封装的是Cortex-M3内核,但具体包括Cortex-M3和其他片上外设是如何进行布线的,以及它所定的原理,ST官方并没有给我们披露。所以,想深刻理解MCU内部结构和时钟树之间对应的关系,包括时钟树和外设之间的关系,其实在官方是找不到锁定解决方案的。
既然没披露,我们也得理解它。因此,这里提出一种"造线方案"。这个方案并不是官方权威的,只是关于后续的理解,提出来让各位在理解这个事儿上面能够更通透。除非将来入职到相关半导体公司,否则我们只能基于现有资料构建模型。当我们体会到这点,至此才算把时钟树对应的由点到面的工作整体搭建成功。至此,对于配置时钟树这个事儿,脑袋当中就有画面感了。
1.3 总线的本质:三类信号线的集合
在打通之前,必须先明确总线的概念。总线并非单根导线,而是由多根线组成的"线组"。在计算机系统中,总线分为三类:

- 地址总线:用于定位目标设备或存储空间。
- 数据总线:传输实际的数据内容。
- 控制总线:包含读写方向控制信号,并特别强调其中包含一根时钟信号线(CLK)。
每一个设备上,通过桥设备接入到整个MCU内部的电路时,是通过这三套线(地址、数据、控制)接入的。控制里包含时钟,就这么理解。其实数据线和地址线也要接入到每个设备当中,官方只不过为了图示清晰,不可能画成几十根线,那样工作量太大也没法看。
1.4 寄存器统一编址与CPU访问机制
片上外设(如GPIO)的寄存器(数据类、控制配置类、状态类)与内存统一编址,CPU通过物理地址直接访问。当CPU执行写指令时,例如代码块中的操作:
c
*(uint32_t *)0x4001100C = 10;

CPU会将目标地址 0x4001100C 放到地址总线、数据 10 放到数据总线、写信号放到控制总线。这个信号经总线矩阵和桥接设备(如AHB到APB桥)最终送达目标外设的对应寄存器。根据访问地址,系统会判定这是外设访问,从而走相应的总线路径。
1.5 设备协同与时钟同步的关键作用
CPU、总线矩阵、桥、外设等均为独立设备,数据传输需各环节"打通"并协同工作。这种协同必须依赖同步机制,而同步的核心载体正是控制总线中的时钟信号线。所有设备需在同一时钟节拍下完成"发送-接收"动作。
当我们把视角切换到外设角度,因为主要是MCU控制外设,所以从外设角度看,你的时钟线就可以接入到不同的平台上了。其实时钟树和这个是关联的。最终的结果,逻辑上这是一个时钟树,以外设角度,时钟线接入不同平台。
二、时钟树如何驱动整个MCU
2.1 时钟树与总线时钟线的物理映射
为了打通理解,我们需要将时钟树的各个分支输出视为物理时钟信号线。例如,将HCLK、PCLK1、PCLK2等分支输出,视为物理时钟信号线,并将其接入到对应总线(AHB、APB1、APB2)的内部时钟线上。



所有连接到这些总线上的设备(CPU、内存、外设)都通过这根共享的时钟线接收同步信号。这就是为什么我们在配置时钟树时,实际上是在配置这些物理连线的通断和频率。
三、MCU 寄存器配置的本质与存储单元原理
3.1 配置的本质:从 CPU 到外设的数据搬运
当我们站在配置视角来理解 MCU 时,首先要打破一个迷思:很多人觉得"配置外设"是一件很高深、很特殊的事情。但实际上,对片上外设做配置,本质上就是修改寄存器。
不管你是修改数据寄存器,还是修改配置寄存器,在硬件底层看来,读写配置寄存器和读写数据寄存器没有任何区别,它们统统都是"读写寄存器"的操作。只不过,当你把数据写进特定的地址(配置寄存器)时,它就起到了配置的作用;写进另一个地址(数据寄存器)时,它就代表了数据。
所以,我们要讨论的核心问题归结为一点:CPU 究竟是如何把数据写到外设里的?
这就涉及到了数据在总线上的流动路径。我们知道,MCU 内部有三套关键的线路在跑信号:
- 数据总线 :上面跑的是实实在在的数据(比如你要配置的数值
10)。 - 地址总线:上面跑的是目标地址(告诉系统这个数据要写给谁)。
- 时钟线:上面跑的是时钟信号。
目前我们还有一个细节没有完全打通,那就是这三者之间是如何协同工作的?地址来了,数据也来了,时钟信号是如何配合,让对应的数据或地址被外设准确拿到的?
3.2 存储单元的工作机制:写入、读取与保持
要理解数据如何被"拿住",我们必须深入到最微观的层面------存储单元。
我们可以把一个存储单元想象成一个带开关的小盒子。

- 写入 :当开关闭合时,写端的数据(比如
1)才能进入盒子内部。 - 读取:读端可以随时把盒子里的内容复制出去,这个过程不会改变内部保存的值。
- 保持 :这是最关键的功能。当开关断开后,无论写端的数据怎么变(哪怕变成了
0),盒子内部依然死死守住刚才写入的那个值(比如1),并且读端持续输出这个老值。



这就是寄存器的物理基础。为了实现这种"保持"功能,存储单元的写入端必须通过一个电子开关(逻辑上类似与门)来控制。这个开关的闭合与断开,就是由我们常说的使能信号(通常由时钟边沿触发)来决定的。
3.3 多位寄存器的构建:并行锁存
单个存储单元只能存 1 bit(0 或 1),但我们在编程时操作的都是 8 位、16 位或 32 位的数据。那么,多位寄存器是怎么来的呢?
答案很简单:并联。
一个 8 位寄存器,就是由 8 个独立的 1 位存储单元并联构成的。
- 独立的写/读端:每个单元都有自己独立的数据输入(写端)和输出(读端),分别对应数据的第 0 位到第 7 位。
- 共享的使能端:这 8 个单元的"开关控制线"是连在一起的,都连接到同一个使能端。
这意味着当我们想要写入一个 8 位数据(例如二进制 0010 0100)时,这 8 个单元的写端会同时接收到对应的高低电平。但是,数据不会立刻进去,它们在门口等着。只有当那个统一的使能信号 (比如时钟的上升沿)到来时,8 个开关同时闭合,这 8 位数据才会被"咔嚓"一下,同时锁存进寄存器内部。

这就是为什么我们说寄存器配置本质上是在修计算器,而且是在时钟的控制下进行的批量数据搬运。
四、时钟信号与总线传输的协同机制
4.1 朴素的数据传输模型
摒弃掉所有复杂的电路细节,我们可以建立一个非常朴素的认识模型:
左边是 CPU ,右边是某个片上外设(比如 GPIO)。
- CPU 内部的一个寄存器里存着原始数据(比如数字
10)。 - 我们需要把这个
10搬运到右边外设的寄存器里去。 - 中间连接它们的是总线。
在这个过程中,CPU 把数据放到总线上,同时把目标外设的地址放到地址总线上。这时候,数据已经在总线上稳定输出了,但外设还没拿到。为什么?因为外设寄存器的"输入开关"还关着呢。
4.2 时钟的核心作用:同步控制的开关
这时候,时钟信号就登场了。
时钟线和数据线、地址线之间是什么关系?答案是:时钟线让"放数据到总线"和"开启目标设备寄存器"这两个动作同步起来。
具体来说,当时钟信号(比如上升沿)到来时,它起到了两个关键作用:
- 控制 CPU 侧:让 CPU 把寄存器里的数据稳稳地放到数据总线上,把地址放到地址总线上。
- 控制外设侧:通过片选逻辑,打开目标外设寄存器的使能开关。
一旦这个开关打开,总线上的数据就顺着通路流进了外设的寄存器。如果没有时钟的统一调度,数据可能在总线上乱跑,或者外设还没准备好数据就丢了。
4.3 关于"同步"的深度理解
这里提到的"同步",并不是指所有事情必须在同一纳秒内发生,而是指步调是有规律的。
确实存在分频的情况。比如,系统可能先让 CPU 打开输出,过了两个时钟周期后,再让片上外设的时钟打开输入开关。这就有了速度差。但这依然是"同步"的,因为它们都是基于同一个时钟源的节拍在运作,无非是经过了几个时钟周期的延迟而已。
无论是上升沿、下降沿,还是高电平、低电平触发,核心逻辑都是一样的:时钟控制了数据传输的节奏。几乎所有片上外设(SPI, I2C, UART 等)的使能和配置原理它们都是一回事------都要在时钟的控制下统一进行。
五、MCU 内部架构全景:时钟树与总线的打通
5.1 从时钟源到 Cortex-M3 内核
现在,我们将目光投向 MCU 的内部架构图,看看刚才讲的理论是如何落地的。

在 MCU 的最左侧,是时钟树的源头。
- 我们有内部高速时钟 HSI (8MHz) 和外部高速时钟 HSE (8MHz)。
- 这些时钟信号经过
/2分频器,进入选择器。 - 选择器输出的信号进入 PLL 锁相环倍频器,将频率倍频到系统所需的高频(比如 72MHz)。
- 倍频后的信号再次经过选择器,进入 AHB 预分频器。
- 最终,AHB 预分频器输出了系统的主时钟 HCLK。
这个 HCLK 至关重要,它直接连接到了中间的 Cortex-M3 内核,为 CPU 的运行提供心跳。
5.2 数据流动的完整路径
请看架构图的中间部分,这里展示了数据是如何从 CPU 流向片上外设的。
-
Cortex-M3 内核侧 :
CPU 内部有一个 8 位寄存器 (由存储单元 A 到 H 组成)。当 CPU 决定发送数据时,它会把这个寄存器的值输出到中间的 8 位数据总线 上。注意,这个输出动作是受 HCLK 控制的。
-
总线传输 :
数据总线就像一条高速公路,连接着左边的 CPU 和右边的外设。图中紫色的箭头清晰地指示了写入方向:从左向右。
-
片上外设侧 :
在架构图的右侧,是具体的某个片上外设 (比如挂载在 APB1 总线上的设备)。它也拥有一个 8 位寄存器(同样由存储单元 A 到 H 组成)。
- 这个外设的时钟来源是 APB1(由 HCLK 进一步分频得到)。
- 外设寄存器的使能端连接到了 APB1 时钟线上。
- 外设寄存器的写端连接到了 8 位数据总线上。
5.3 一次完整的写操作复盘
当 CPU 想要配置这个外设时:
- CPU 在 HCLK 的驱动下,将配置数据(比如
0x55)放到 8 位数据总线上。 - 同时,地址总线选中了这个外设。
- APB1 时钟信号产生一个上升沿。
- 这个上升沿传导到右侧外设寄存器的使能端。
- 外设内部那 8 个存储单元的开关瞬间闭合。
- 数据总线上的
0x55被锁存进外设的寄存器中。 - 上升沿结束,开关断开,数据被永久保持,直到下一次写入。
至此就深刻理解 ARM CPU 和 GPIO 等片上外设的数据是如何通过总线导通的,以及时钟在其中扮演的"统一指挥官"角色。
结语
