3、电源管理单元(PMU)配置:PMU工作模式,唤醒事件配置,电源域划分

好,咱们接着聊PMU。这东西说白了就是芯片的“总电闸”加“值班室”。你想想看,一个嵌入式设备要低功耗,不能一直开着所有电路,但又不能完全死掉——得留个“耳朵”听命令。PMU就是干这个的。

我个人习惯,拿到一款新芯片,第一件事就是翻它的PMU章节。为什么?因为功耗优化的天花板,其实在PMU这里就定死了。你后面软件再怎么调,也跳不出硬件划分的框框。

3.1 PMU的工作模式

PMU不是只有“开”和“关”两种状态。实际上,它有好几个档位。我把它分成三类:

  • 运行模式(Active):全速跑,所有电源域都供电。这时候功耗最高,但性能也最强。
  • 睡眠模式(Sleep):CPU停了,但外设和内存还在供电。适合那种“随时要响应”的场景。
  • 深度睡眠模式(Deep Sleep):大部分电路断电,只留PMU和几个关键外设(比如RTC、唤醒IO)。这是我最常用的模式。

嗯,这里要注意:不同厂家的叫法不一样。ST叫Stop和Standby,NXP叫VLPS和LLS,TI叫Deep Sleep和Hibernate。但本质都一样——用功耗换响应时间。

核心原则:睡眠越深,唤醒越慢。你不可能既要纳秒级唤醒,又要微安级功耗。这是物理定律,绕不过去。

3.2 唤醒事件配置

唤醒事件,就是那个“耳朵”。我遇到过不少工程师,功耗降下来了,但设备唤不醒了——这就尴尬了。

常见的唤醒源有这些:

  • GPIO中断:最常用。按键、传感器触发都可以。
  • RTC闹钟:定时唤醒。比如每秒钟起来发个心跳包。
  • 比较器输出:模拟信号触发。比如电池电压低于阈值就唤醒。
  • 通信接口:UART的RX引脚、CAN总线活动等。

配置的时候,我建议你画一张表:

唤醒源 适用场景 典型功耗 唤醒时间
GPIO下降沿 按键唤醒 ~1μA ~10μs
RTC闹钟 定时任务 ~0.5μA ~100μs
UART RX 串口唤醒 ~2μA ~50μs

我曾经在一个项目里,用了GPIO唤醒,结果发现引脚配置错了——上拉电阻没开,导致电平不确定,芯片一直在唤醒和睡眠之间来回跳。功耗反而比正常跑还高。所以,唤醒配置一定要做去抖处理,硬件上串个RC,软件上做个延时判断。

我的小技巧:调试唤醒时,先别急着测功耗。用示波器抓唤醒引脚的波形,确认信号干净了,再去看电流。省得走弯路。

3.3 电源域划分

电源域划分,是PMU配置里最体现功力的地方。说白了,就是把芯片内部电路分成几个“独立电表”,哪个不用就拉闸。

典型的划分方式:

  • VDD_CORE:CPU核心、Cache、内部总线。功耗大户,睡眠时必须关。
  • VDD_PERI:外设模块。UART、SPI、I2C这些。按需供电。
  • VDD_BACKUP:备份域。RTC、备份寄存器、唤醒逻辑。永远不断电。
  • VDD_IO:IO口供电。有些芯片可以独立控制。

我见过一个失败的案例:某团队把WiFi模块和MCU放在同一个电源域里。结果MCU想睡,WiFi还在发包,整个系统功耗降不下来。后来把WiFi单独拉一个域,用PMU的负载开关控制,功耗直接降了80%。

注意:电源域切换时,要考虑“上电顺序”。有些外设对供电时序很敏感,比如DDR内存,必须先给VDD再给VTT。乱来会烧芯片。我吃过这个亏,那次返修了200多块板子...

最后,给个代码片段。这是我在STM32L4上配置PMU进入Stop模式的例子:

// 进入Stop模式,保留SRAM,RTC唤醒
void enter_stop_mode(void)
{
    // 配置PMU寄存器
    PWR->CR1 |= PWR_CR1_LPMS;      // 选择低功耗模式
    PWR->CR1 |= PWR_CR1_FPDS;      // 闪存掉电
    
    // 配置唤醒源:RTC闹钟
    EXTI->IMR1 |= EXTI_IMR1_IM17;  // 使能RTC中断
    EXTI->RTSR1 |= EXTI_RTSR1_RT17; // 上升沿触发
    
    // 进入睡眠
    __WFI();  // Wait For Interrupt
}

嗯,代码很简单,但背后要考虑的东西不少。比如:进入Stop前,要不要关掉ADC?DMA传输完了吗?这些细节,决定了你的系统是“优雅入睡”还是“强行断电”。

总结一下:PMU配置,就是选模式、配唤醒、划电源域。这三步走对了,低功耗就成功了一半。剩下的,就是软件层面的配合了——咱们下一章聊。