ZZZ-05-时钟树

时钟树的功能:车间里的“传动轴”

想象 STM32 是一个巨大的自动化工厂,里面有几百个加工车间(外设,比如 GPIO 是控制灯的车间,USART 是通信车间)。

  • 主时钟(HCLK/SYSCLK):是工厂里的大发动机。
  • 外设时钟:是从大发动机连接到各个车间的传动皮带。

STM32 的设计逻辑是: 为了极度省电,工厂默认所有的传动皮带都是拆掉的。也就是说,虽然大发动机(主频)在转,但动力传不到具体车间里。如果你想让 GPIO 车间工作,你必须先手动“合上电闸”或者“挂上皮带”。

为什么要搞得这么麻烦?(核心逻辑:低功耗)

51 单片机默认时钟是全开的,简单但费电。 STM32 作为高性能芯片,集成了非常多的外设。如果这些外设的时钟全部默认开启:

  1. 功耗爆炸:即使你没用这些外设,数字电路在时钟驱动下也会不断产生翻转电流,导致芯片发烫,电池瞬间没电。
  2. 电磁干扰:无用的高频信号会产生不必要的干扰。

所以,STM32 遵循“按需分配”原则:你不用的东西,我不给供能。

3. 时钟树:动力是怎么传导的?

时钟的源头有很多,就像工厂可以由自备发电机供电,也可以由电网供电。

  1. HSE (高速外部时钟):通常是电路板上那个金属外壳的晶振(比如 8MHz)。它最准。
  2. HSI (高速内部时钟):芯片内部自带的,虽然没那么准,但能应急。
  3. PLL (锁相环/倍频器):这是最神奇的地方。它能把 8MHz 的微弱动力,像加了涡轮增压一样,翻好几倍变成 72MHz 或 168MHz。
graph LR %% 时钟源部分 subgraph Sources [1.时钟源-水源] HSE[HSE 外部高速晶振
通常 8MHz] HSI[HSI 内部高速时钟
约 8MHz, 不够准] LSE[LSE 外部低速晶振
32.768kHz, 给RTC用] LSI[LSI 内部低速时钟
40kHz, 给看门狗用] end %% 倍频部分 subgraph Processing [2.倍频与切换-水处理] PLLMux{时钟源选择} PLL[PLL 锁相环
倍频器] SYS_Mux{系统时钟选择} HSE --> PLLMux HSI --> PLLMux PLLMux --> PLL PLL -->|x9| SYS_Mux HSE --> SYS_Mux end %% 总线分发部分 subgraph Bus [3.总线预分频-水管] SYSCLK((SYSCLK 系统时钟
通常 72MHz)) AHB_Pre[AHB 预分频器] APB1_Pre[APB1 低速预分频器
最高 36MHz] APB2_Pre[APB2 高速预分频器
最高 72MHz] SYS_Mux --> SYSCLK SYSCLK --> AHB_Pre AHB_Pre --> APB1_Pre AHB_Pre --> APB2_Pre end %% 外设部分 subgraph Peripherals [4.外设-水龙头] AHB_Pre --> DMA[DMA / 复位控制器] APB1_Pre --> TIM2[Timer 2,3,4] APB1_Pre --> UART2[UART 2,3] APB1_Pre --> I2C[I2C 1,2] APB2_Pre --> GPIO[GPIO A, B, C...] APB2_Pre --> UART1[UART 1] APB2_Pre --> ADC[ADC 1,2] APB2_Pre --> SPI1[SPI 1] end %% 样式美化 style SYSCLK fill:#f96,stroke:#333,stroke-width:2px style PLL fill:#fcf,stroke:#333 style Sources fill:#e1f5fe,stroke:#01579b style Peripherals fill:#fff9c4,stroke:#fbc02d

为什么要有这么多时钟源

  • HSE (High-Speed External):你的开发板上那个金属的小疙瘩(晶振)。它是最准的,做串口通信、USB 等对时间敏感的任务必须用它。
  • HSI (High-Speed Internal):芯片内置的电阻电容震荡产生。优点是启动快、不用钱,缺点是受温度影响大,会“跑偏”。
  • LSE/LSI:就像家里的闹钟电池,功率极低,专门给 RTC(实时时钟/万年历) 或 看门狗(防止程序死机) 这种需要 24 小时待命的模块用。

不同的总线(APB1 与 APB2)

这是初学者最容易搞混的地方:

  • APB2 (高速总线):通常运行在 72MHz。它连接的是最重要的外设,比如 GPIO(控制灯、按键快不快全靠它)、UART1、ADC。
  • APB1 (低速总线):为了节能,它的上限通常只有 36MHz。挂载的是一些没必要跑那么快的模块,比如一般的定时器、I2C 通信等。

1、这里可能会产生疑问,为什么将 I2C 和 UART 挂在到 APB1 低速总线上,我们先来看看所谓的“低速”总线 APB1

  • APB1 总线频率:通常是 $36\text{ MHz}$(即每秒钟翻转 36,000,000 次)。
  • UART 常用速率:$115200\text{ bps}$(约 $0.1\text{ MHz}$)。
  • I2C 常用速率:标准模式 $100\text{ kbps}$,快速模式 $400\text{ kbps}$(约 $0.4\text{ MHz}$)。

结论:即使是所谓的“低速”总线 APB1($36\text{ MHz}$),它的速度也是 I2C 和 UART 物理传输速率的 几十倍甚至几百倍。 对于这些外设来说,APB1 提供的带宽已经绰绰有余了。把它们挂在 $72\text{ MHz}$ 的 APB2 上,完全是浪费。

2、你可能会问:既然 UART 都不需要高速,那 GPIO 为什么要高速?

  • GPIO(通用输入输出):有时候我们需要用 GPIO 模拟一些非常复杂的协议,或者输出极高频率的脉冲(比如驱动高速功率管)。如果 GPIO 总线慢,输出的波形就会“抖动”或者变圆,无法精准控制。
  • ADC(模数转换):ADC 需要在极短的时间内对模拟电压进行采样。采样频率越高,还原的信号越准,这必须依靠高速时钟支持
  • TIM1/TIM8:这些是高级定时器,用于控制电机的精准补差。如果时钟不够快,控制精度就会下降。

3、一个有趣的例外:UART1

如果你仔细看时钟树,你会发现 USART1 往往是挂在 APB2(高速)上的,而 USART2, 3 挂在 APB1 上。这是为什么呢?

  1. 启动与刷机:STM32 的串口下载(Bootloader)通常默认使用 USART1。为了保证在各种复杂情况下都能快速、可靠地通信,官方把它放在了高速总线上。
  2. 最高上限:如果你真的需要极限的串口波特率(比如几兆比特每秒),USART1 能够提供比其他串口更高的上限。

PLL(倍频器)是核心魔术师

如果你外接了一个 8MHz 的晶振,但你希望芯片跑在 72MHz。怎么办? PLL 就是干这个的。它能把输入的 8MHz “乘”上一个倍数(比如 9 倍),得到 72MHz。

重点理解:总线层级

在学习时钟树时,你会看到两个重要的“分发器”,它们叫 APB 总线:

  • APB1:低速总线(最高通常 36MHz 或 42MHz)。连接的是比较慢的外设(如串口 UART2、普通定时器)。
  • APB2:高速总线(最高通常 72MHz 或 84MHz)。连接的是重要的、需要快的模块(如 GPIO、串口 UART1、高级定时器)。

记住这个知识点: 当你在查手册开启时钟时,一定要看清楚你的外设是挂在 APB1 还是 APB2 下。挂错了总线,时钟函数就调错了。

Licensed under CC BY-NC-SA 4.0