4. 工作模式详解(上):运行模式、休眠模式与深度休眠模式

各位同学,今天我们来聊聊 MCUCMS32 的三种核心工作模式。说实话,低功耗设计里最基础也最关键的就是搞懂这几种模式。我见过不少工程师,代码写得飞起,结果一测功耗直接傻眼——就是因为没把模式切换玩明白。

咱们先看一张总览图,把三种模式的关系理清楚。

MCUCMS32 三种工作模式切换总览 运行模式 CPU 全速运行 休眠模式 CPU 暂停,外设可选运行 深度休眠模式 仅极少数外设运行 中断 / 事件唤醒 核心思路:能睡就睡,能浅睡就不深睡,唤醒后快速回到运行模式处理任务

4.1 运行模式下的功耗优化

很多人觉得运行模式就是让 CPU 全速跑,没什么好优化的。其实不然。运行模式下的功耗优化,说白了就是「别让 CPU 做无用功」。

我个人习惯把运行模式优化分成三个层面:

  • 时钟频率动态调整:不是所有任务都需要 48MHz。比如轮询按键,8MHz 绰绰有余。我建议根据任务紧急程度动态切换系统时钟。
  • 外设按需使能:用不到的 SPI、I2C、UART 模块,记得关掉时钟。我在项目中遇到过,一个没用的 UART 模块开着,白白多吃了 2mA 电流。
  • 等待指令替代忙等:别用 while(flag==0); 这种傻等。用 WFI 或 WFE 指令,让 CPU 在等待时进入低功耗状态。

运行模式功耗优化清单

优化项典型功耗节省实现方式
降低主频0.5~3 mA修改 PLL 分频系数
关闭未用外设时钟0.1~2 mARCC 外设时钟使能寄存器
使用 WFI/WFE 等待0.3~1 mAWFI 指令替代忙等
优化代码执行路径0.2~0.8 mA减少循环次数,使用查表法

举个例子。我之前做一款手持设备,主频跑 48MHz,电池续航只有 6 小时。后来我把主频降到 16MHz,配合外设时钟管理,续航直接翻到 14 小时。你想想看,只是改了几行代码,效果立竿见影。

4.2 休眠模式的进入与退出

休眠模式,也叫 Sleep Mode。这个模式下 CPU 时钟停了,但 SRAM 和寄存器内容都保留,外设时钟可以继续跑。

进入休眠模式很简单,就两步:

// 步骤1:设置 SLEEPDEEP 位为 0
SCB->SCR &= ~(1 << 2);

// 步骤2:执行 WFI 或 WFE 指令
__WFI();

嗯,这里要注意。WFI 和 WFE 的区别很多人搞混。WFI 是等到中断来了才唤醒,WFE 是只要有事件就唤醒。我个人习惯用 WFI,因为唤醒时机更可控。

退出休眠模式的方式有几种:

  • 任何中断:只要中断使能了,就能唤醒 CPU
  • 事件:通过事件线唤醒,适合外设间协同
  • 复位:最粗暴的方式,一般不推荐

小技巧:如果你想让某个外设中断唤醒,但又不希望它执行完整的中断服务函数,可以在中断入口判断一下,如果是唤醒中断,直接清标志位返回。这样可以减少不必要的处理时间。

我曾经在一个项目中,用定时器中断每 10ms 唤醒一次 CPU,执行完 ADC 采样后继续休眠。这样平均电流从 5mA 降到了 0.8mA。说白了,休眠模式就是「短平快」——进去快,出来也快。

4.3 深度休眠模式的配置

深度休眠模式,也叫 Deep Sleep Mode。这个模式更狠——CPU 停了,大部分外设也停了,只有少数几个模块还能工作,比如 RTC、LPTIM、LPUART。

进入深度休眠模式的配置稍微复杂一点:

// 步骤1:设置 SLEEPDEEP 位为 1
SCB->SCR |= (1 << 2);

// 步骤2:选择电压调节器模式(可选)
// 0 = 正常模式,1 = 低功耗模式
PWR->CR |= (1 << 1);  // 低功耗模式

// 步骤3:配置唤醒源
// 使能 RTC 唤醒
RTC->CR |= (1 << 10);  // WUTE 位

// 步骤4:执行 WFI
__WFI();

避坑指南:我曾经在深度休眠模式下踩过一个坑——唤醒后系统时钟没有自动恢复。原因是进入深度休眠前,我把系统时钟切换到了内部低速振荡器,但唤醒后没有切回来。解决办法是在唤醒后的第一件事就是重新配置系统时钟。

深度休眠模式的唤醒源有限,常见的有:

唤醒源特点典型应用
RTC 闹钟定时唤醒,精度高周期性数据采集
外部中断响应快,引脚触发按键唤醒、传感器触发
LPUART低功耗串口唤醒无线模块数据接收
比较器模拟信号触发电池电压监测唤醒

三种模式的功耗对比,我整理了一张表:

模式典型电流唤醒时间保留内容
运行模式5~50 mA—全部
休眠模式0.5~5 mA几微秒SRAM + 寄存器
深度休眠模式1~50 μA几十微秒SRAM(可选保留)

你看,深度休眠模式功耗最低,但唤醒时间也最长。所以实际项目中,我一般这样用:

  • 需要频繁响应的任务(比如按键扫描)→ 用休眠模式
  • 需要长时间待机的任务(比如传感器每隔 1 分钟采集一次)→ 用深度休眠模式
  • 需要快速处理的任务(比如通信协议栈)→ 用运行模式,但做好时钟和外设管理

核心原则:在满足实时性要求的前提下,尽可能选择功耗更低的模式。不要为了省电而牺牲功能,也不要为了性能而浪费电。