1. 低功耗概览:为什么需要低功耗?

做嵌入式开发这些年,我见过太多工程师把精力全扑在性能和功能上,等到产品做出来了,才发现电池撑不过三天。说实话,这种返工最痛苦——硬件改不了,软件从头优化,老板还催着交货。

低功耗不是「锦上添花」,而是很多产品的生死线。你想想看,一个智能门锁如果一个月换次电池,用户会怎么想?一个医疗贴片如果撑不到48小时,医生敢用吗?

核心认知: 低功耗设计不是「省电模式」,而是「在正确的时间,让正确的模块工作,让不工作的模块彻底休息」。

1.1 为什么我们需要认真对待功耗?

我最早接触低功耗,是在一个户外数据采集项目里。设备用4节AA电池,要求连续工作6个月。当时我用的是普通STM32F1系列,怎么优化都只能撑2个月。后来换了STM32L4,同样的算法,同样的传感器,功耗直接降了80%。

从那以后我明白了一个道理:选对芯片只是第一步,真正决定续航的是你的设计思路。

低功耗的需求主要来自这几个场景:

  • 电池供电设备:物联网终端、可穿戴设备、无线传感器——这类产品续航直接决定用户体验
  • 能量采集系统:靠太阳能、振动、温差发电,功耗必须低于采集功率才能持续运行
  • 散热受限场景:密闭壳体、高温环境,功耗高了温度压不住,系统会降频甚至宕机
  • 长期待机设备:烟雾报警器、门磁、水表,十年不换电池不是噱头,是真需求
我的经验: 做低功耗设计,第一件事不是翻数据手册,而是搞清楚「你的产品到底有多少时间在干活,多少时间在睡觉」。很多项目80%的功耗浪费在待机状态下的漏电和无效轮询上。

1.2 STM32L4系列低功耗特性总览

STM32L4系列是ST专门为低功耗场景打造的。我习惯把它比作「会呼吸的单片机」——它知道什么时候该深呼吸,什么时候该屏住气。

先看一张总览图,把L4系列的功耗模式和资源状态理清楚:

STM32L4 低功耗模式与资源状态总览 运行模式 (Run) 全速运行,所有外设可用 睡眠模式 (Sleep) CPU停,外设继续工作 低功耗运行 (LP Run) 降频运行,电压降低 停止模式 0/1/2 (Stop) CPU停,SRAM可选保持 待机模式 (Standby) 仅保留RTC和备份域 VBAT模式 仅RTC供电,VDD断开 唤醒方式:EXTI中断 / RTC闹钟 / 比较器触发 / 复位 / WKUP引脚 典型功耗对比(@ 25°C,VDD=3.3V) 模式 典型电流 唤醒时间 SRAM保持 Run @ 80MHz ~100 μA/MHz — 全部 Stop 2 ~1.1 μA ~5 μs 全部 Standby ~0.1 μA ~50 μs 丢失

这张图我每次培训都会拿出来讲。你看,从Run到Standby,功耗差了整整三个数量级。但代价是什么?唤醒时间变长,SRAM内容丢失。这就是低功耗设计的核心矛盾——省电和省事,你总得选一个。

1.3 低功耗设计的核心思想

做了十几年嵌入式,我总结出三条铁律。这三条不是从书上看来的,是烧了好几块板子、熬了好几个通宵换来的。

1.3.1 按需供电——别让不该工作的模块通电

这是最基础也最容易被忽略的。我见过一个项目,ADC模块在休眠时没关,白白多耗了20μA。20μA看起来不多,但乘以365天,电池容量就这么被吃掉了。

具体怎么做?

  • 关闭未使用的外设时钟:STM32L4的RCC寄存器可以单独控制每个外设的时钟门控
  • GPIO不要浮空:浮空引脚会反复翻转,产生额外的动态功耗。我习惯把不用的引脚设为模拟模式或上拉输出
  • 禁用不用的模拟模块:ADC、DAC、比较器、OPAMP,不用就关掉
我曾经踩过的坑: 有一次调试一个低功耗项目,Stop模式电流始终下不来。查了三天,最后发现是一个GPIO配置成了浮空输入,引脚上连的传感器在休眠时输出高阻,导致引脚电平不确定,IO口内部电路反复翻转。改成内部下拉后,电流从12μA降到了1.5μA。

1.3.2 时间分片——干完活就睡,别磨蹭

低功耗设计的本质是「占空比管理」。你想想看,一个传感器节点如果每秒只采样一次,每次耗时1ms,那它99.9%的时间都在睡觉。这时候,睡眠电流和唤醒时间就是决定续航的关键。

STM32L4的Stop 2模式是我最常用的。1.1μA的电流,5μs的唤醒时间,SRAM全部保持。这意味着你可以把现场数据存在RAM里,醒来后直接接着干,不用重新初始化。

// 进入Stop 2模式的典型代码
void enter_stop2_mode(void)
{
    // 关闭不需要的外设时钟
    __HAL_RCC_ADC12_CLK_DISABLE();
    __HAL_RCC_SPI1_CLK_DISABLE();
    __HAL_RCC_USART2_CLK_DISABLE();
    
    // 配置唤醒源(例如RTC闹钟)
    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
    
    // 进入Stop 2模式
    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
    
    // 醒来后重新配置系统时钟
    SystemClock_Config();
}

1.3.3 动态电压与频率调节——别用大炮打蚊子

STM32L4支持多种电压调节范围(Range 1/2)和频率缩放。说白了就是:活重的时候跑快点,活轻的时候跑慢点。

我做过一个测试:同样的数据处理任务,用80MHz跑完需要10ms,电流100μA/MHz;用4MHz跑需要200ms,但电流只有50μA/MHz。算下来总能耗反而更低。为什么?因为动态功耗和频率成正比,但静态功耗基本不变。跑慢点虽然时间长,但总能量消耗可能更少。

电压范围 最大频率 典型电流 适用场景
Range 1 80 MHz ~100 μA/MHz 密集计算、通信处理
Range 2 26 MHz ~60 μA/MHz 常规轮询、数据采集
LP Run 2 MHz ~30 μA/MHz 待机监听、慢速传感器
我的建议: 不要一上来就想着用Standby模式省最多的电。先算清楚你的任务周期。如果每100ms就要醒一次,Stop 2模式比Standby更合适——虽然Standby电流更低,但唤醒时间长了10倍,总能耗反而更高。

1.4 本章小结

低功耗设计不是玄学,也不是靠运气。它是一套系统化的方法:

  • 选对模式:根据任务间隔和唤醒速度,在Sleep/Stop/Standby之间做选择
  • 管好外设:不用的模块彻底断电,GPIO状态要确定
  • 算总账:别只看静态电流,要把唤醒时间和动态功耗一起算进去

嗯,这一章先到这里。后面的章节我们会逐个深入每种模式的具体配置、实测数据,以及我在项目中遇到的那些「看起来没问题,一测电流就翻车」的案例。准备好了吗?