2. STM32电源系统架构:电压调节器、电源域与备份域

做低功耗设计,第一件事就是搞清楚芯片的“血管”怎么走的。电源系统就像人的心脏和动脉,你只有知道哪条路供电、哪条路可以关掉,才能真正把功耗降下来。

我记得刚入行那会儿,有个项目电池续航死活达不到要求。我拿着万用表到处测,最后发现是VBAT引脚上挂了个不该挂的负载。嗯,从那以后,我每次画板子前都会先把电源域理一遍。

2.1 三大电源域:VDD、VDDA、VBAT

STM32把芯片内部划分成几个独立的供电区域,这叫“电源域”。每个域可以单独控制通断,这是低功耗的根基。

电源域 供电对象 典型电压 低功耗关键点
VDD域 内核、数字外设(GPIO、定时器、USART等)、Flash、SRAM 1.8V ~ 3.6V 进入Stop/Standby模式时可切断大部分数字逻辑供电
VDDA域 模拟外设(ADC、DAC、比较器、PLL、复位电路) 2.0V ~ 3.6V(与VDD独立) 不用ADC时,可以关闭VDDA供电或降低采样率
VBAT域 备份寄存器、RTC、LSE振荡器 1.65V ~ 3.6V(电池供电) 主电源掉电后,由纽扣电池维持RTC和备份数据

核心原则:哪个域不用,就切哪个域的供电。但要注意——VDDA和VDD的电压差不能超过0.3V,否则芯片内部会出问题。我吃过这个亏,板子焊好发现ADC读数飘得厉害,查了半天是VDDA比VDD低了0.4V。

2.2 电压调节器:内核的“心脏泵”

STM32内部有一个电压调节器(Voltage Regulator),它把外部VDD电压转换成内核需要的1.2V或1.8V。这个调节器有三种工作模式,直接决定了芯片的功耗水平。

  • MR(Main Regulator,主调节器):全速运行模式,输出电流大,适合Run模式。功耗最高。
  • LPR(Low-Power Regulator,低功耗调节器):输出电流小,适合Sleep/Stop模式。功耗降低约50%~70%。
  • 关闭(Power Down):Standby模式下,调节器完全关断,内核逻辑掉电。功耗最低,但唤醒后需要重新初始化。

我个人的习惯是:如果项目需要频繁唤醒(比如1秒一次),我会用LPR模式,因为MR切到LPR的切换时间只有几个微秒,几乎无感。但如果唤醒间隔超过10秒,我直接切Standby,让调节器彻底关掉。

小技巧:在Stop模式下,你可以通过PWR_CR寄存器中的LPDS位选择使用MR还是LPR。LPDS=1时使用LPR,功耗从几十μA降到几个μA。但要注意,LPR模式下Flash处于掉电状态,唤醒后第一次取指会有等待周期。

2.3 备份域:掉电也不丢数据

备份域是STM32里最“顽强”的部分。主电源VDD断了,只要VBAT引脚上还挂着纽扣电池,RTC照常走,备份寄存器里的数据也不丢。

备份域包含以下资源:

  • 备份寄存器(Backup Registers):20个16位寄存器(BKP_DR1~BKP_DR20),用于存储关键配置或状态。
  • RTC(实时时钟):支持秒、分、时、日期,闹钟和唤醒功能。
  • LSE振荡器:32.768kHz晶振,为RTC提供精准时钟。
  • 入侵检测(TAMPER):检测到外部入侵时,可以自动清除备份寄存器内容。

避坑指南:我曾经在一个产品中把备份寄存器当普通RAM用,频繁读写。结果发现纽扣电池寿命只有标称的一半。后来查手册才知道,备份寄存器每次写入都需要使能PWR和BKP时钟,而且写操作会消耗额外电流。所以——只在系统初始化时写一次,运行时只读不写。

2.4 电源系统整体架构图

下面这张图把STM32的电源脉络画清楚了。你对照着看,每个域怎么供电、怎么切换,一目了然。

STM32电源系统架构图 VDD (1.8V~3.6V) VDDA (2.0V~3.6V) VBAT (1.65V~3.6V) 电压调节器 MR / LPR / 关闭 输出 1.2V / 1.8V 模拟域 ADC / DAC / 比较器 备份域 RTC / BKP寄存器 内核域 CPU / Flash / SRAM 数字外设域 GPIO / 定时器 / USART 电压差 ≤ 0.3V RTC + LSE 32.768kHz 说明: 1. VDD域包含内核和数字外设,由电压调节器供电,可独立关闭。 2. VDDA域为模拟外设供电,与VDD独立但电压差需≤0.3V。 3. VBAT域在主电源掉电后由电池维持RTC和备份寄存器。

2.5 电源模式与功耗对照

不同的电源域组合,对应不同的低功耗模式。我整理了一张对照表,方便你选型时快速参考。

模式 电压调节器 内核域 数字外设域 模拟域 备份域 典型电流
Run MR 运行 运行 运行 运行 几十mA
Sleep MR 停止 运行 运行 运行 几mA
Stop (MR) MR 停止 停止 可选 运行 几十μA
Stop (LPR) LPR 停止 停止 可选 运行 几μA
Standby 关闭 掉电 掉电 掉电 运行 几百nA

个人经验:Stop模式下,如果你不需要ADC,记得把VDDA域也关掉。我有个项目在Stop模式下测到12μA,关掉VDDA后直接降到3μA。做法很简单:在进入Stop前,调用HAL_PWR_DisableAnalogMode(),或者直接操作PWR_CR寄存器的VOS位。

2.6 备份域操作实战

最后,我分享一段备份域操作的代码。这段代码我在好几个产品里用过,稳定运行了好几年。

// 使能备份域访问
void BKP_Enable(void)
{
    // 1. 使能PWR和BKP时钟
    RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
    
    // 2. 允许访问备份域寄存器
    PWR->CR |= PWR_CR_DBP;
    
    // 3. 等待稳定
    while(!(PWR->CR & PWR_CR_DBP));
}

// 写入备份寄存器(仅在初始化时调用)
void BKP_WriteReg(uint16_t reg, uint16_t data)
{
    BKP_Enable();
    BKP->DR[reg] = data;
}

// 读取备份寄存器(运行时频繁调用)
uint16_t BKP_ReadReg(uint16_t reg)
{
    return BKP->DR[reg];
}

注意:备份域写入操作需要使能PWR和BKP时钟,并且设置DBP位。但读取操作不需要这些步骤,直接读寄存器即可。所以——把写操作放在初始化阶段,运行时只读,能省不少电。