3、深度睡眠模式:深度睡眠与睡眠的区别、稳压器配置、内存保持策略

好,咱们接着聊深度睡眠。说实话,很多工程师把睡眠和深度睡眠混为一谈,觉得不就是睡得更沉一点嘛。其实差别大了去了。我在一个电池供电的传感器项目里就吃过这个亏——明明进了睡眠,功耗还是降不下来,后来一查,核心压根没进深度睡眠模式。

3.1 深度睡眠 vs 睡眠:到底差在哪?

先看一张对比表,你一眼就能明白区别在哪。

特性 睡眠模式 (Sleep) 深度睡眠模式 (Deep Sleep)
CPU 时钟 停止 停止
系统时钟 (SYSCLK) 运行 停止或降频
稳压器 (Regulator) 正常模式 (Range 1) 低功耗模式 (Range 2 / 低电压)
唤醒延迟 几微秒 几十到几百微秒
典型电流 (STM32L4) ~100 µA/MHz ~1 µA 左右
RAM 保持 全部保持 可配置保持区域

看到没?核心差异在稳压器和系统时钟。睡眠模式只是停了 CPU 的时钟,但稳压器还在满负荷工作,系统时钟(比如 HSI、HSE)也还在跑。深度睡眠则把系统时钟也停了,稳压器切到低功耗档位,这才是真正的“省电模式”。

关键指标:深度睡眠的电流通常是睡眠模式的 1/100 甚至更低。如果你的产品要求待机电流在 10 µA 以下,睡眠模式基本没戏,必须上深度睡眠。

3.2 稳压器配置:Range 1 vs Range 2

稳压器配置是深度睡眠里最容易踩坑的地方。我刚开始做低功耗驱动时,以为只要调个寄存器就行,结果发现唤醒后外设工作不正常——因为电压不够。

Cortex-M 内核(比如 STM32L 系列)的稳压器通常有多个工作范围:

  • Range 1 (正常模式):输出电压 ~1.2V,支持最高主频,功耗高。
  • Range 2 (低功耗模式):输出电压 ~1.0V,主频受限(通常 ≤ 2 MHz),功耗低。

进入深度睡眠时,你需要手动把稳压器从 Range 1 切到 Range 2。怎么切?看代码:

/* 进入深度睡眠前的稳压器配置示例 (STM32L4) */
void enter_deep_sleep(void) {
    // 1. 设置稳压器为低功耗模式 (Range 2)
    HAL_PWREx_EnableLowPowerRunMode();  // 或者直接操作 PWR_CR1 寄存器

    // 2. 选择深度睡眠模式
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    // 注意:这里用 PWR_MAINREGULATOR_ON 表示进入睡眠,但实际深度睡眠需要配合 PWR_CR1 的 LPDS 位

    // 更直接的做法:
    // PWR->CR1 |= PWR_CR1_LPDS;   // 低功耗深度睡眠
    // SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;  // 设置 SLEEPDEEP 位
    // __WFI();
}

注意:唤醒后,稳压器不会自动切回 Range 1。你必须在唤醒中断服务程序里手动恢复 Range 1,否则外设(比如 ADC、DMA)可能因为电压不足而工作异常。我曾经在量产前才发现这个问题,差点改 PCB。

3.3 内存保持策略:哪些 RAM 能丢?

深度睡眠下,RAM 不是全部保持的。以 STM32L4 为例,SRAM 分为多个区域:

  • SRAM1 (96 KB):默认保持,但可以关闭。
  • SRAM2 (32 KB):默认保持,也可以单独关闭。
  • 备份 SRAM (4 KB):始终保持(由 VBAT 供电)。

你想想看,如果你的应用只需要保存几个关键变量(比如计数值、状态标志),完全没必要让整个 SRAM 都保持供电。关掉不必要的 RAM 区域,能再省 50% 的深度睡眠电流。

配置方法:

/* 关闭 SRAM2 以降低深度睡眠功耗 (STM32L4) */
void config_ram_retention(void) {
    // 关闭 SRAM2 的保持
    PWR->CR2 |= PWR_CR2_SRAM2STOP;

    // 或者更细粒度:只保留 SRAM1 的低 32 KB
    // 通过 PWR->CR1 的 RRL 位域配置
}

我的习惯:在进入深度睡眠前,把需要保留的数据(比如 RTC 闹钟值、传感器校准参数)拷贝到备份 SRAM 里,然后关掉所有主 SRAM。这样深度睡眠电流可以降到 0.5 µA 以下。

3.4 深度睡眠的完整流程

下面这张 SVG 图总结了深度睡眠的完整状态机,你对照着看会更清楚。

深度睡眠模式状态机 深度睡眠模式状态机 运行模式 准备深度睡眠 稳压器 → Range 2 配置 RAM 保持区域 执行 WFI / WFE 深度睡眠 唤醒事件 说明:唤醒后必须手动恢复稳压器 Range 1 和 RAM 保持配置,否则外设可能异常

流程其实不复杂:运行 → 准备(稳压器 + RAM)→ 执行 WFI/WFE → 深度睡眠 → 唤醒后恢复。但每一步都有细节,尤其是唤醒后的恢复,很多人会忘。

3.5 避坑指南:我踩过的三个坑

  1. 唤醒后外设死掉:稳压器没切回 Range 1。解决办法是在唤醒 ISR 里第一件事就是恢复稳压器。
  2. RAM 数据丢失:关掉了不该关的 SRAM 区域。我建议你在调试阶段先全部保持,确认哪些变量必须保留后,再逐步关闭。
  3. 唤醒延迟比预期长:深度睡眠的唤醒延迟主要来自稳压器从 Range 2 恢复到 Range 1 的时间。如果你的应用对唤醒时间敏感(比如响应按键),可以考虑用睡眠模式代替。

总结一下:深度睡眠的核心就是“稳压器降档 + 系统时钟停 + RAM 按需保持”。配置时记住三步:切稳压器、配 RAM、设 SLEEPDEEP 位。唤醒后别忘了恢复。做到这几点,你的待机电流就能从毫安级降到微安级。