时钟系统与功耗:HSE、HSI、LSE、LSI 时钟源的选择,PLL 配置对功耗的影响,时钟门控技术

时钟系统,说白了就是 STM32 的心脏。心跳多快,功耗就有多高。很多朋友做低功耗项目,一上来就盯着睡眠模式、停止模式调,结果发现电流还是降不下去。我告诉你,问题八成出在时钟源的选择上。

这一章,咱们就把时钟源和功耗的关系彻底捋清楚。我会结合自己踩过的坑,告诉你什么时候用 HSE,什么时候切 HSI,PLL 到底该不该开。

1. 四大时钟源,各有各的脾气

STM32 内部有四个时钟源,每个都有自己的功耗特性。我整理了一张表,方便你对比:

时钟源 全称 典型频率 启动时间 典型功耗 精度
HSE 高速外部晶振 4-16 MHz ~2 ms 高(~500 μA) 极高(±10 ppm)
HSI 高速内部 RC 8 MHz(可微调) ~10 μs 中(~100 μA) 一般(±1%)
LSE 低速外部晶振 32.768 kHz ~1 s 低(~0.5 μA) 极高(±5 ppm)
LSI 低速内部 RC ~32 kHz(实际有偏差) ~50 μs 极低(~0.2 μA) 差(±5%~±10%)

看到没?HSE 启动要 2 毫秒,功耗 500 微安。LSI 启动只要 50 微秒,功耗 0.2 微安。这差距,你想想看。

核心原则:不需要高精度时,别开 HSE。不需要高频率时,别开 PLL。这是低功耗设计的第一条铁律。

2. 我的选择策略:按场景切源

我个人习惯,把项目场景分成三类:

  • 全速运行场景:比如采集传感器数据、做 FFT 运算。这时候用 HSE + PLL,跑到 72 MHz 甚至更高。功耗高,但没办法,性能要保证。
  • 待机监听场景:比如等待按键、等待 RTC 闹钟。这时候切到 HSI,关掉 PLL。频率降到 8 MHz,功耗能降 60% 以上。
  • 深度休眠场景:比如电池供电的温湿度采集,一小时醒一次。这时候只用 LSI 驱动 RTC 和独立看门狗。系统电流能压到 2 μA 以下。

我在一个水表项目里遇到过一个问题:设备用电池供电,要求 5 年寿命。一开始用 HSE + PLL 跑 72 MHz,然后进 Stop 模式。结果发现电池半年就挂了。后来改成:唤醒后切 HSI 跑 8 MHz,采集完立刻进 Standby 模式,RTC 用 LSI 驱动。电流从 15 μA 降到了 1.8 μA。嗯,这才是正确的做法。

3. PLL 配置对功耗的影响

PLL 这东西,是个功耗大户。为什么?因为它内部有压控振荡器(VCO),还有反馈分频器。频率越高,VCO 的电流越大。

我实测过一组数据,用的是 STM32F103:

配置 系统频率 运行电流(典型)
HSI 直接输出 8 MHz ~8 mA
HSE + PLL (x9) 72 MHz ~50 mA
HSE + PLL (x6) 48 MHz ~35 mA
HSE 直接输出 8 MHz ~10 mA

看到了吗?从 8 MHz 到 72 MHz,频率翻了 9 倍,电流翻了 6 倍。而且 PLL 本身就有基础功耗,即使输出频率很低,只要 PLL 使能,它就在耗电。

注意:PLL 的 VCO 频率范围通常是 64-128 MHz(不同系列有差异)。如果你只需要 24 MHz,不要用 PLL 从 8 MHz 倍频到 24 MHz。直接切 HSI 或 HSE 分频,关掉 PLL,功耗更低。

4. 时钟门控技术:白送的功耗优化

时钟门控,英文叫 Clock Gating。说白了就是:不用某个外设的时候,把它的时钟关掉。

STM32 的 RCC 寄存器里,有一堆 xxxEN 位。比如 RCC_APB2ENR_USART1EN、RCC_AHB1ENR_GPIOAEN。这些位就是时钟门控的开关。

我见过很多工程师,初始化的时候把所有外设时钟都打开了,然后就不管了。结果芯片在睡眠模式下,电流还是居高不下。为什么?因为外设时钟虽然没在工作,但时钟树还在给它们送时钟信号,触发器还在翻转,动态功耗一直在消耗。

正确的做法是:

// 错误示范:只开不管
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_TIM1EN;

// 正确做法:用前开,用完关
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;  // 开 USART1 时钟
// ... 配置 USART1,发送数据 ...
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN; // 关 USART1 时钟

小技巧:进入低功耗模式前,遍历一遍所有外设的时钟使能寄存器,把没用的都关了。我习惯写一个 DisableUnusedPeriphClocks() 函数,在进入 Sleep/Stop 模式前调用。这个习惯帮我省了不少电。

5. 知识结构图:时钟与功耗的关系

下面这张图,把时钟源、PLL、时钟门控和功耗的关系画清楚了。你可以把它当作本章的思维导图:

时钟系统与功耗关系图 时钟系统与功耗关系图 HSE 外部晶振 HSI 内部 RC LSE 外部 32k LSI 内部 32k PLL 倍频(功耗大户) 分频器(低功耗) SYSCLK 系统时钟 时钟门控(RCC_xxxENR 寄存器) USART / SPI TIM / ADC GPIO / DMA 关键:频率越高功耗越大,PLL 使能即耗电,时钟门控可关闭未用外设的时钟

6. 避坑指南:我踩过的三个坑

做低功耗调试这些年,我在时钟系统上栽过不少跟头。挑三个典型的跟你说说:

  • 坑一:RTC 用 LSI,时间越跑越偏。 我曾经在一个数据记录仪项目里,RTC 用 LSI 驱动。结果一天下来,时间误差超过 5 分钟。后来用频率计一测,LSI 实际输出只有 28 kHz,偏差 12.5%。解决方案:对时间精度有要求时,必须用 LSE。
  • 坑二:退出 Stop 模式后,HSE 起振失败。 我遇到过芯片从 Stop 模式唤醒后,HSE 起振超时,系统卡死在 HSI 上。后来查手册才发现,HSE 起振需要时间,如果唤醒后立刻切到 HSE,可能还没稳定。解决方案:唤醒后先切 HSI,等 HSE 稳定后再切换。
  • 坑三:时钟门控没关干净,休眠电流多出 10 μA。 有一次我怎么都找不到漏电点,最后用示波器量时钟输出脚,发现 SPI1 的时钟还在翻转。原来初始化 SPI 时开了时钟,但进休眠前忘了关。从那以后,我写了个专门的函数,进休眠前把所有外设时钟扫一遍。

调试小工具:用 RCC->AHBENR、RCC->APB1ENR、RCC->APB2ENR 这三个寄存器的值,可以快速判断哪些外设时钟还开着。我习惯在调试时把这三个值通过串口打印出来,一目了然。