STM32 低功耗共有三种模式:

Sleep 睡眠模式 、Stop 停止模式、Standby 待机模式。

三种模式的 操作图解 地址:

本文将重点拆解 Standby 待机模式 的代码实现、关键事项 。

参考资源:

目录

一、 STM32 三种低功耗模式 区别

1、睡眠模式 Sleep Mode 

2、停止模式 Stop Mode

二、工程准备

1、基础工程

2、烧录问题

三、Standby 待机模式 代码实现

1. 进入 Standby 待机 模式

2. 唤醒后的处理

四、 验证 & 测试 

五、常见问题 & 避坑指南

         


        

一、 STM32 三种低功耗模式 区别

       

1、睡眠模式 Sleep Mode 

  • 功耗:芯片工作电流约 10~20mA (参考值)
  • 特点:CPU暂停在SLEEP这一行;外设正常工作;唤醒时间极快; 
  • 注意1:能被所有中断事件唤醒;若无法进入 SLEEP,优先检查是否未关闭 SysTick 等频繁中断。
  • 注意2:被中断唤醒后,先进入对应中断函数执行,完成后再运行 SLEEP 下一行代码。
  • 注意3:SLEEP 模式无硬件唤醒标志,唤醒后无需额外处理;通常自定义软件标志配合业务逻辑。
停止资源 CPU内核停止运行、内核时钟关闭、程序暂停运行
保持资源

系统时钟、所有外设时钟保持运行

GPIO 口状态保持运行时的电平

内存、寄存器 数据保持不变

唤醒方式 任意中断事件均可唤醒 (如 GPIO中断、Systick、UART、RTC 等)
唤醒后 程序正常运行,无需重新初始化时钟 / 外设。
适合场景

短时间无需 CPU 运算,

但需要外设(如串口、ADC、定时器)持续工作的场景

   

2、停止模式 Stop Mode

  • 功耗:芯片工作电流约 1mA (参考值)
  • 特点:系统时钟关闭;CPU和外设停止;内存数据保持;唤醒后仅需恢复系统时钟
停止资源

CPU 与所有外设停止工作

内核时钟、外设时钟,主时钟(HSE/HSI)被关闭

外设停止工作

保持资源

低速时钟(LSI/LSE,用于 RTC)继续运行

内核1.8V供电保持

内存、寄存器 数据保持不变

GPIO 口状态保持运行时电平

唤醒方式

外部中断 EXTI

RTC 闹钟

唤醒后

不需要重新初始化 UART、SPI、ADC等外设

必须重新配置系统时钟(如启用 HSE/PLL)

适合场景 需要低功耗、同时要求快速唤醒、数据不丢失的场合。

  

3、待机模式 Standby Mode

  • 功耗:芯片工作电流约 4uA (参考值)
  • 特点:几乎断电,内存数据丢失,唤醒后相当于复位
停止资源

内核1.8V电源关闭,内存、寄存器数据全部丢失

内核与外设时钟关闭,但 LSI/LSE 可在备份域继续给 RTC 供电

IO 口变为高阻态(模拟输入/浮空输入)

保持资源

备份域(Backup Domain):备份寄存器、RTC 备份区域;

WAKEUP唤醒引脚 PA0

RTC 相关引脚

复位引脚

唤醒方式

WAKEUP 引脚(PA0)上升沿

RTC 闹钟

唤醒之后

程序从 从头运行 (相当于复位 )(不会回到 Standby下一行)

可通过 PWR_CSR 的 SBF / WUF 标志判断是 [待机唤醒] 还是 [上电复位]

适合场景 长时间休眠、对功耗要求极致的电池供电设备、遥测终端等

注意 1 :WAKEUP 引脚(PA0)仅在 Standby 模式下具备硬件自动唤醒功能,Sleep / Stop 模式下 PA0 不具备此功能,必须配置为 EXTI 外部中断 才能唤醒。

注意 2 :IWDG 独立看门狗,只能复位芯片!不能唤醒!因为 IWDG 不会产生中断。

  


  

二、工程准备

1、基础工程

三种低功耗模式均支持 RTC 闹钟唤醒,因此统一使用 RTC 闹钟作为工程模板,添加低功耗测试。

不熟悉 RTC 闹钟的朋友,参考教程:

本文所用工程模板:【 Keil 工程文件 -- RTC 闹钟 】

当然,你可以使用自己的工程模板、需要的唤醒方式:

  • Sleep 睡眠模式:任意中断事件唤醒。
  • Stop 停止模式:外部中断 EXTI 、RTC闹钟
  • Standby 待机模式:WAKEUP 引脚 PA0 的上升沿 、 RTC 闹钟

   

2、烧录问题

STM32 进入 Stop、Standby 低功耗模式后,芯片内核停止工作,无法正常响应烧录信号,可能出现无法下载、烧录失败的情况。

以下是不同仿真器的解决方法:

     

STLink 仿真器的解决方法:

  • 方法1:按着板子复位按键,不放手,keil 点击 Load 后,马上放开复位按键。利用复位后的空档期识别烧录信号。
  • 方法2:BOOT0接线3.3V,按一次复位按键,烧录。拔掉BOOT0接线,按一次复位按键,即可。  

  

CMSIS-DAP 仿真器的解决方法:

  • Connect这一项:选择 under Reset,即可随时烧录。

      

JLink 仿真器:

  • Stop 模式,不影响,随时可烧录。
  • Standby 模式,方法1:按着板子复位按键,不放手,keil 点击 Load 后,马上放开复位按键。利用复位后的空档期识别烧录信号。
  • Standby 模式,方法2:BOOT0接线3.3V,按一次复位按键,烧录。拔掉BOOT0接线,按一次复位按键,即可。  

     


三、Standby 待机模式 代码实现

   

与 Sleep、Stop 模式相比,Standby 模式有以下关键特点:

  • 唤醒后程序复位,内存、寄存器数据都会丢失(除备份域)
  • 无需恢复系统时钟,因为复位后系统会自动重新初始化时钟(从 HSI 启动,再由SystemClock_Config() 配置为 HSE)。
  • 如果后备域可用,可以通过 备份寄存器 保存少量数据(最多 20 个 32 位寄存器,芯片型号不同数量有别),用于判断唤醒源或恢复关键状态。

本节以 RTC 闹钟 B 周期性唤醒 为例,演示进入 Standby 待机模式、唤醒后判断原因并执行对应任务。

方案仅作思路参考,实际项目可灵活扩展。

     

1. 进入 Standby 待机 模式

进入 Standby 待机模式本身很简单,只需调用HAL库函数:HAL_PWR_EnterSTANDBYMode ();

真正的重点在于:进入前的准备、以及进入的时机。

我们编写一个用户函数:把进入 Standby 前的准备工作,整合在一起 。

具体操作:

  • main.c文件 ,在 /* USER CODE BEGIN 0 */ 区域
  • 在闹钟B中断回调函数的下方,添加函数。(按你所用中断回调函数位置而定)
/******************************************************************************
 * 函  数: EnterStandbyMode
 * 功  能: 进入 STANDBY 待机模式
 * 说  明: 1. 内核电源关闭,内存、寄存器数据丢失(备份域除外)
 *          2. 唤醒后系统复位,程序从 main 函数重新执行
 *          3. 进入前需清除 PWR 唤醒标志,否则可能无法进入
 *          4. 唤醒源:仅两种合法唤醒方式, RTC闹钟、 WAKEUP引脚(PA0上升沿)
 * 参  数: 无
 * 返回值: 无
 * 备  注: 最后修改_2026年03月25日
 ******************************************************************************/
void EnterStandbyMode(void)
{
    /* 打印提示 */
    printf("\r\n");                                            // 打印 换行
    printf("① 即将进入 Standby 待机模式! \r\n");              // 打印 提示
    
    /* 开启 PWR 时钟 */
    __HAL_RCC_PWR_CLK_ENABLE();                                //开启PWR时钟; (新版本HAL库不再需要手动开启)

    /* 清除相关标志 */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);                         // 清除唤醒标志 (关键)
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);                         // 清除待机标志 (建议)
    
    /* 配置唤醒源 */
    RTC_SetAlarmB(5);                                          // 设置RTC的闹钟B, 5秒后触发一次
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);                  // 使能WAKEUP引脚 (PA0上升沿触发)

    /* 进入 STANDBY 待机模式 */
    HAL_PWR_EnterSTANDBYMode();                                // 进入 Standby 模式

    /* 注意:以下代码永远不会被执行。唤醒后是复位重启 */
    printf("② 此行永远不会执行!\r\n");
}

重要 1:唤醒源

函数里,示例了两个唤醒源:RTC闹钟B、唤醒引脚PA0 。(Standby 仅有两个唤醒源)

① RTC闹钟B,设置为5秒后触发。

② WAKEUP 唤醒引脚。在STM32F407上,它固定是PA0。使能  WAKEUP 引脚后,无需配置PA0的 GPIO 模式和中断,硬件会自动检测PA0的电平变化(上升沿唤醒)。很多板商的开发板上都已引出 PA0 作为按键,闲时是低电平,当按键按下时PA0是高电平(唤醒 Standby)。

  

重要2: 清除唤醒标志

每次进入Standby前,必须清除PWR 的 WU 唤醒标志,否则可能无法进入 (立刻退出)。
 

重要3:这个函数永远不会运行到底

进入Standby待机模式后,芯片就关闭内核供电、停止工作,不再执行下面行的代码。

直到被唤醒,程序复位重新运行。

因此,上面函数进入Standby模式后的下面行,永远也不会被执行。这是Standby 与 Sleep、Stop的一个重要区别!

     

2. 唤醒后的处理

StandBy 模式 仅支持两个唤醒源:WAKEUP引脚、RTC闹钟。

程序唤醒后 (即复位运行),可以通过硬件标志 PWR_FLAG_SB,得知复位来源:待机模式唤醒、正常上电复位 。

具体操作:

  • main()函数,在外设初始化后,编写以下代码:
  • 1- 判断 复位源
  • 2- 调用 EnterStandbyMode(), 进入待机模式
/* 判断复位来源 */
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) )                  // 待机唤醒后的复位 
{
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);                 // 清除待机唤醒标志; 注意先清标志再干活 
    // TODO: 在这里添加唤醒后的特殊处理                // 执行待机唤醒的特定任务
    printf("\r系统是从 STANDBY 待机模式 唤醒!\r\n");
}
else                                                   // 正常上电复位 
{
    printf("\r系统是正常上电启动!\r\n");              // 打印提示
    /* TODO: 在这里执行完整初始化 */                   // 执行完整初始化、任务
}
  

/* 准备进入 Standby 待机模式 */
HAL_Delay(1000);
EnterStandbyMode();                                    // 进入 Standby 待机模式

/* 下面的代码永远不会运行 */
 

添加完成后,位置参考如下图:

这里只是示例。真实项目改为由特定条件进入Standby。

           


         

四、 验证 & 测试 

  

现在,Standby 模 的所有工作:清除标志、进入、唤醒、判断复位源,都已处理完毕。   

编译、烧录后,串口助手输出如下图:

  • 程序上电运行后,判断复位源
  • 1秒后,准备进入Standby模式 
  • 进入前:设置闹钟B 5秒后触发、使能WAKEUP引脚
  • (进入了Standby,直到被 闹钟 或 WAKEUP 唤醒)
  • 注意:图中可以看到,即使被闹钟唤醒,但唤醒后没有执行闹钟B回调函数里的printf。因为 Standby 唤醒后只能是从头运行程序 !!​​   


    

五、常见问题 & 避坑指南

  

1. 无法进入 STANDBY 模式(电流依然较高)

可能原因:

  • 未清除 PWR_FLAG_WU 唤醒标志,导致进入 STANDBY 后立即被唤醒。
  • 外部中断或 RTC 闹钟频繁触发,导致刚进入就被唤醒。
  • PA0 引脚悬空,受噪声影响误触发。

解决方法:

  • 在 EnterStandbyMode() 函数开头调用 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU)。
  • 确保唤醒源在进入前已配置正确,且不会在短时间内再次触发。
  • 对 PA0 引脚加上拉电阻。

   

2. 唤醒后 RTC 时间错乱

原因:

  • 待机模式下,RTC 会继续运行,但如果使用 LSI,其精度较低,长时间待机可能导致时间漂移。

解决:

  • 如需高精度时间,使用外部 LSE 晶振。唤醒后应重新读取 RTC 时间,无需重新设置。

   

3. 仿真器无法烧录、无法连接

参考第二节“烧录问题”的解决方法。

4. PA0 唤醒引脚与外部中断冲突

如果既配置了 PA0 为 WKUP 引脚,又使能了 EXTI 中断,可能会产生双重唤醒。建议仅使用 WKUP 功能,无需配置 EXTI。

5. 如何测试电流

开发板断开USB供电。

万用表调至mA档,串联在电源回路 (红笔接5V电源正极,黑笔压在开发板5V排针,板子GND接电源GND)。


  

文毕,欢迎指正、交流。~~

Logo

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

更多推荐