STM32L4 低功耗实战:把待机电流从 20 µA 压到 1.5 µA
背景
一块纽扣电池供电的 BLE 温湿度节点,目标是 一年寿命。CR2032 标称 220 mAh,折算平均电流要压到 < 25 µA。
广播占空比已经做得很低,瓶颈就落在 Stop2 模式的静态电流上。
第一次测量:20 µA。目标:< 2 µA。
工具
- 万用表:只能看稳态,µA 下噪声大,别指望看瞬态。
- Joulescope / Power Profiler Kit:必备,能看 µs 级电流尖峰。
- 示波器 + 电流环路:土办法但够用。
排查清单
1. GPIO 浮空 → 省了 8 µA
未用的 GPIO 不能悬空。MX_GPIO_Init 里确认所有未用引脚:
1 | GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 或者 INPUT + PULL_DOWN |
Analog 模式是最省的,因为施密特触发器关闭,没有翻转漏电。
2. 调试接口没关 → 省了 1.2 µA
SWD 的 PA13/PA14 在 Stop 模式下仍消耗电流。生产固件里显式关掉:
1 | HAL_DBGMCU_DisableDBGSleepMode(); |
注意:关了之后板子就烧不进去了,所以用条件编译:
1 |
|
3. LSE 启振电流 → 省了 0.3 µA
默认 LSE driver 强度太大,对于 6 pF 晶振用 Medium low 就够:
1 | __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_MEDIUMLOW); |
4. VREFBUF 和 ADC → 省了 3 µA
ADC 测完就要关:
1 | HAL_ADC_Stop(&hadc1); |
5. 外设时钟 & DMA → 省了 4 µA
进入 Stop2 之前,显式关闭所有不需要在低功耗下运行的外设时钟。
这条很容易忘:HAL 把外设 init 做得很完整,但没人给你把时钟收尾。
6. 传感器 I²C 上拉 → 省了 1.8 µA
SHT40 工作时不耗电(已进入 sleep),但 I²C 线上 10 kΩ 上拉到 3 V 的漏电逃不掉。
把上拉电阻改到 100 kΩ,并让 MCU 在不通信时把 SCL/SDA 拉低(或者断开上拉 VCC)。
7. RTC 已经是必须的,就剩它了
最终 Stop2 + RTC 运行时的静态电流稳定在 1.5 µA,达标。
总账
| 优化项 | 节省 | 累计电流 |
|---|---|---|
| 初始 | - | 20.0 µA |
| GPIO 模拟模式 | 8 µA | 12.0 µA |
| 关 SWD | 1.2 µA | 10.8 µA |
| LSE 驱动档 | 0.3 µA | 10.5 µA |
| ADC/VREFBUF | 3 µA | 7.5 µA |
| 外设时钟 | 4 µA | 3.5 µA |
| I²C 上拉 | 1.8 µA | 1.7 µA |
| 杂项收尾 | 0.2 µA | 1.5 µA |
一点经验
- 一次只改一个地方,每次都用 Joulescope 测,否则不知道是哪条起了作用。
- 测 48 h 平均电流比瞬时峰值有意义,BLE 广播的瞬间峰会冲到 10 mA。
- 最终评估用实际电池跑,LDO / DCDC 的静态电流不在 MCU 侧。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 射频与嵌入式技术博客!