1. 低功耗概览:STM32L4 系列低功耗特性总览

做嵌入式这么多年,我见过不少工程师一上来就怼着代码调功耗,结果折腾半天发现选错了模式。说白了,低功耗设计的第一步不是写代码,而是搞清楚你的芯片到底能睡多深。

STM32L4 系列是意法半导体专门为低功耗场景打造的。它基于 Cortex-M4 内核,带 FPU 和 DSP 指令,性能不差,但真正厉害的是它的功耗模式设计。我刚开始用 L4 的时候,也被那一堆模式搞得有点晕——Run、Sleep、LP Run、LP Sleep、Stop、Standby…… 每个模式功耗差好几个数量级,唤醒时间也完全不同。

这一章我们先搭个框架,把 L4 的低功耗家底摸清楚。

1.1 功耗模式对比

先看这张图,我把 L4 的功耗模式按功耗从高到低排了个序。你一眼就能看出,从 Run 到 Standby,电流差了 6 个数量级。

STM32L4 功耗模式层级图 Run ~100 µA/MHz ~ 数 mA 唤醒: 立即 Sleep ~50 µA/MHz ~ 数 mA 唤醒: 几个 CPU 周期 LP Run ~8 µA/MHz ~ 500 µA 唤醒: 立即 LP Sleep ~3 µA/MHz ~ 200 µA 唤醒: 几个 CPU 周期 Stop 0 ~30 µA (RTC + RAM 保持) 唤醒: ~5 µs Stop 1 ~3 µA (RTC + RAM 保持) 唤醒: ~5 µs Stop 2 ~1 µA (RTC + RAM 保持) 唤醒: ~5 µs Standby ~100 nA (仅备份域) 唤醒: ~50 µs 功耗降低 →

这张图我建议你存下来。每次选模式的时候,对着它看一眼,基本不会选错。

核心原则:功耗越低,唤醒越慢,保留的外设越少。没有免费的午餐。

1.2 各模式详解

下面我把每个模式拆开讲。你注意看表格里的「保留内容」和「唤醒源」这两列,这是选型的关键。

模式 典型电流 CPU 状态 RAM 保持 主要唤醒源 典型场景
Run ~100 µA/MHz 运行 全部 — 正常处理
Sleep ~50 µA/MHz 暂停 全部 任何中断/事件 等待外设完成
LP Run ~8 µA/MHz 运行 (低频) 全部 — 低负载持续处理
LP Sleep ~3 µA/MHz 暂停 (低频) 全部 任何中断/事件 低频等待
Stop 0 ~30 µA 关 全部 RTC / 外部中断 / 部分外设 秒级休眠
Stop 1 ~3 µA 关 全部 RTC / 外部中断 / 部分外设 分钟级休眠
Stop 2 ~1 µA 关 全部 RTC / 外部中断 / 部分外设 分钟级休眠
Standby ~100 nA 关 丢失 RTC / WAKEUP 引脚 / 复位 长时间休眠

这里有个细节我提醒你一下:Stop 0/1/2 的区别不只是电流。Stop 2 关闭了更多外设时钟,但 RAM 内容全部保留。我有个项目做温湿度记录仪,采样间隔 5 分钟,用的就是 Stop 2 + RTC 唤醒,整机平均电流做到了 2.3 µA 左右。

我的习惯:如果休眠时间小于 1 秒,用 Stop 0;1 秒到 1 分钟,用 Stop 1 或 Stop 2;超过 1 分钟,直接上 Standby。当然,前提是你的数据能接受 RAM 丢失。

1.3 功耗测量方法

说到测量,我踩过不少坑。最早我用万用表直接串在电源上测,结果发现读数跳来跳去,根本不准。后来才明白,低功耗电流是脉冲式的——芯片醒来那几十微秒电流可能冲到几毫安,然后迅速掉回微安级。万用表的积分时间太长,测出来的是平均值,但你看不到瞬态行为。

我个人习惯用这几种方法:

  • 精密万用表(6.5 位以上):测稳态电流,比如 Standby 模式。Fluke 8846A 或 Keysight 34461A 都行。
  • 示波器 + 电流探头:看瞬态波形,比如从 Stop 唤醒时的电流尖峰。探头带宽建议 50 MHz 以上。
  • 专用功耗分析仪:比如 Joulescope 或 Otii,能同时测电压、电流、功率,还能积分算总能耗。我最近的项目基本都用 Otii,省事。
  • 串联采样电阻法:低成本方案,用 10Ω 电阻串在电源上,示波器测电阻两端电压。注意电阻压降会影响芯片供电,别选太大。

我曾经犯过的错:用普通万用表测 Stop 2 模式的电流,读数显示 0.8 µA,我以为很完美。结果用示波器一看,芯片每 100 ms 偷偷醒来一次,电流尖峰 3 mA,持续 200 µs。算下来平均电流其实有 6 µA 左右。所以记住:低功耗测量一定要看波形,不能只看数字。

1.4 快速上手:测量一个最简单的 Standby 电流

说了这么多,我们来动动手。下面这段代码让 STM32L4 进入 Standby 模式,你可以用它验证你的测量环境。

/* 进入 Standby 模式示例 */
#include "stm32l4xx_hal.h"

void Enter_Standby(void)
{
    /* 1. 清除唤醒标志 */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

    /* 2. 使能电源时钟 */
    __HAL_RCC_PWR_CLK_ENABLE();

    /* 3. 设置 Standby 模式 */
    HAL_PWR_EnableSleepOnExit();  /* 可选:退出中断后自动休眠 */
    HAL_PWR_EnterSTANDBYMode();

    /* 不会执行到这里 */
}

烧录后,用你的万用表串在 VDD 上,应该能看到电流掉到 100 nA 左右。如果读数偏高,检查一下有没有外部上拉电阻或者未使用的 GPIO 在漏电。

一个小技巧:进入 Standby 前,把所有未使用的 GPIO 配置为模拟模式(GPIO_MODE_ANALOG),可以再省几十 nA。别问我怎么知道的——有一次我测出来 500 nA,查了半天发现是 PA3 悬空,在数字输入模式下来回翻转。