在电池供电设备(如IoT传感器、可穿戴设备、远程控制器)或任何对能耗敏感的应用中,低功耗设计是延长设备续航的关键。STM32微控制器提供了丰富且灵活的低功耗模式,让开发者能在性能与功耗之间找到最佳平衡点。本文将深入探讨这些模式的核心原理、应用场景及实战要点。

一、为什么需要低功耗模式?


延长电池寿命: 直接决定产品竞争力(如智能手表、环境监测传感器)。

降低发热: 减少散热需求,提升系统稳定性。

满足环保/能效标准: 符合日益严格的行业规范。

能量收集应用: 使设备能在微弱能源(如太阳能、动能)下工作。

二、STM32 核心低功耗模式详解


1.Sleep Mode (睡眠模式)

执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠
在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态
WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
WFE指令进入睡眠模式,可被唤醒事件唤醒

核心原理: 仅关闭CPU时钟,外设(如GPIO、UART、TIMER)仍可运行。中断或事件可立即唤醒。

状态保存: SRAM 和寄存器内容完全保留。程序从进入 Stop 模式指令的下一条指令继续执行(前提是唤醒源不是复位)。

进入方式: WFI (Wait For Interrupt) 或 WFE (Wait For Event) 指令。

状态保存: 所有寄存器和 SRAM 内容完全保留。CPU 上下文(寄存器值)由硬件自动保存和恢复。

功耗: 较高(mA级),但唤醒速度最快(仅需几μs)。

适用场景: 短暂空闲等待外部事件(如按键检测、轮询间隔)。

2.Stop Mode (停止模式)

执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来
在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态
当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟
当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时
WFI指令进入停止模式,可被任意一个EXTI中断唤醒
WFE指令进入停止模式,可被任意一个EXTI事件唤醒

核心原理: 关闭所有时钟(HCLK, PCLK1, PCLK2),关闭高速晶振(HSE)。SRAM和寄存器内容保持。电压调节器可配置为低功耗模式。

进入方式: 配置PWR_CR寄存器,执行WFI/WFE。

状态保存: SRAM 和寄存器内容(除备份域)全部丢失。唤醒后程序从复位向量重新开始执行(如同上电复位或复位引脚复位)。

唤醒源: 外部中断(EXTI)、RTC闹钟/事件、特定外设事件(如LPUART)。

功耗: 极低(μA级别,典型值1.7~20μA)。唤醒后需重新配置时钟系统。

适用场景: 需要较长时间休眠、快速唤醒且保存运行状态的场景(如周期性数据采集)。

3.Standby Mode (待机模式)

执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行
整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电
在待机模式下,所有的I/O引脚变为高阻态(浮空输入)
WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式

核心原理: 功耗最低的模式。关闭除备份域(RTC、备份寄存器、唤醒逻辑)外的所有电路。SRAM和寄存器内容丢失(除备份寄存器)。相当于一次“软复位”。

进入方式: 设置PWR_CR寄存器的PDDS和LPDS位 + SLEEPDEEP位,执行WFI/WFE。

唤醒源: NRST引脚复位、WKUP引脚上升沿、RTC闹钟/事件、独立看门狗复位。

功耗: 最低(nA级别,典型值0.1~2μA)。唤醒后程序从头开始执行(相当于复位)。

适用场景: 需要超长待机时间,对唤醒后状态无要求(如远程控制器、防盗报警器)。

三、关键唤醒源与应用实例


外部中断 (EXTI): 最常用,如按键唤醒、传感器信号触发。

RTC (实时时钟): 精准定时唤醒,实现周期性任务(如每小时采集一次温湿度)。

特定外设: LPUART (低功耗串口) 接收数据唤醒、LPTIM (低功耗定时器) 超时唤醒。

WKUP 引脚: 专为待机/关机模式设计的超低功耗唤醒引脚。

应用实例:

        智能水表: 大部分时间处于Stop模式(保持数据),RTC定时唤醒抄表或磁干扰(WKUP)唤醒进行读数。

        GPS追踪器: 运动时用Sleep模式,静止时进入Stop模式节省电量,定时或运动传感器唤醒上报位置。

        温湿度传感器节点: 采集后通过LoRa发送数据,随后进入Deep Sleep/Standby模式,RTC定时(如每10分钟)唤醒工作。

四、低功耗设计实战要点


1.精准测量:

         使用高精度电流表(如μA级)测量各模式的实际功耗,不同型号、外设配置差异巨大。

2.外设管理:

        进入低功耗前: 务必关闭所有不需要的外设时钟 (__HAL_RCC_xxx_CLK_DISABLE()) 和模块。

        未使用引脚: 配置为模拟输入(无上下拉)以最小化漏电流。

3.IO状态:

        避免引脚浮空,根据外部电路合理配置上下拉。

        输出引脚状态需匹配外部电路需求(避免无谓电流)。

4.数据保存策略:

        Stop模式:数据存于SRAM即可。

        Standby/Shutdown模式:关键数据必须存入备份寄存器 (RTC_BKPxR) 或Flash。

5.调压器配置:

        部分模式(如Stop)可选择主调压器或低功耗调压器,后者功耗更低但唤醒稍慢。

代码实现

1.Sleep Mode (睡眠模式)

使用cubemx随机配置一个中断,我这里使用串口,主循环前开启接收中断。

主要看主要代码部分,其他代码都是调试,显示结果的。

一定要关闭systick,他每秒钟都会产生中断,也会打断睡眠模式,睡眠模式结束之后要及时开启

    HAL_UART_Receive_IT(&huart1, &rx_buffer[0], 1);

while (1)
  {
    HAL_UART_Transmit(&huart1, "start", strlen("start"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);
    OLED_ShowString(2,1,"num:");
    num++;
    OLED_ShowNum(2,5,num,3);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_Delay(2000);

    //主要代码
    HAL_SuspendTick();//关闭systick
    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI);//进入睡眠模式
    HAL_ResumeTick();//开启systick
    
    HAL_UART_Transmit(&huart1, "end", strlen("end"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);
   
  }

结果

2.Stop Mode (停止模式)

使用cubemx随机配置一个外部中断,我这里使用按键。

主要看主要代码部分,其他代码都是调试,显示结果的。

进入停机模式再唤醒之后时钟不会再次倍频,需要自己手动设置。

while (1)
  {
    HAL_UART_Transmit(&huart1, "start", strlen("start"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);
    OLED_ShowString(2,1,"num:");
    num++;
    OLED_ShowNum(2,5,num,3);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_Delay(2000);

    //主要代码
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);//进入停机模式
    SystemClock_Config();//重新设置时钟

    HAL_UART_Transmit(&huart1, "end", strlen("end"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);

  }

结果:

你会发现串口已经无法唤醒停机模式了,他需要外部中断。自己尝试一下就明白了,我不再演示了。

3.Standby Mode (待机模式)

这个我们介绍两种唤醒方式:wake-up引脚上升沿和实时时钟

wake-up引脚上升沿

cuebmx配置

其他基本配置我不多说,主要是在sys中勾选wake-up这个配置选项

注意一定要清除标志位

  //这两句一定要加上,不然会直接唤醒待机模式
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB))__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_WU))__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//清除标志位
    
while (1)
  {
    HAL_UART_Transmit(&huart1, "start", strlen("start"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);
    OLED_ShowString(2,1,"num:");
    num++;
    OLED_ShowNum(2,5,num,3);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_Delay(2000);
    //主要代码

    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);    //使能wkup
    HAL_PWR_EnterSTANDBYMode();            //进入待机模式

    HAL_UART_Transmit(&huart1, "end", strlen("end"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);
    
  }

实时时钟计数

cubemx配置

勾选开启RTC,配置时钟源为外部低速时钟,先在RCC中开启才能在时钟配置页面配置。

//实现自己的时间读写函数
void RTC_SetAlarm(uint32_t s) {
  //获取当前时间
  RTC_TimeTypeDef time;
  HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
  //设置闹钟时间
  RTC_AlarmTypeDef alarm={0};
  alarm.AlarmTime.Hours = time.Hours;
  alarm.AlarmTime.Minutes = time.Minutes;
  alarm.AlarmTime.Seconds = time.Seconds+s-1;
  HAL_RTC_SetAlarm(&hrtc, &alarm, RTC_FORMAT_BIN);

}

//主循环开启前清除标志位
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB))__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_WU))__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//清除标志位

while (1)
  {
    HAL_UART_Transmit(&huart1, "start", strlen("start"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);
    OLED_ShowString(2,1,"num:");
    num++;
    OLED_ShowNum(2,5,num,3);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_Delay(2000);
    //主要代码
    RTC_SetAlarm(6);        //设置6s之后时钟唤醒
    HAL_PWR_EnterSTANDBYMode();    //进入待机模式

    HAL_UART_Transmit(&huart1, "end", strlen("end"), 1000);
    HAL_UART_Transmit(&huart1, "\r\n", strlen("\r\n"), 1000);

  }

结果:

你会发现结尾的end没有打印,这是因为,每次进入待机模式之后再唤醒,程序都会从头开始执行,相当于软复位。

五、总结:选择合适的“休眠”姿势


追求极速响应 → Sleep Mode

需保存状态且周期性工作 → Stop Mode

追求最长待机,状态可丢弃 → Standby/Shutdown Mode

成功的低功耗设计 = 理解模式原理 + 精确测量 + 严格的外设/IO管理。 深入钻研数据手册,结合实际测试,你就能让STM32在“节能冠军”的道路上走得更远!

提示: 本文内容基于通用STM32系列(如F1/F4/L4)。具体实现细节请务必参考你所使用的STM32型号的官方参考手册和数据手册。

通过合理利用STM32强大的低功耗模式,你的嵌入式设备将拥有更持久的生命力,在电池供电和物联网应用中脱颖而出。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐