STM32 低功耗共有三种模式:
Sleep 睡眠模式 、Stop 停止模式、Standby 待机模式。
三种模式的 操作图解 地址:
- 【STM32 + CubeMX】低功耗 -- Sleep 睡眠模式
- 【STM32 + CubeMX】低功耗 -- Stop 停止模式
- 【STM32 + CubeMX】低功耗 -- Standby 待机模式 【本文】
本文将重点拆解Standby 待机模式 的代码实现、关键事项 。
参考资源:
- Keil 工程下载 -- 【 STM32F407 -- 待机模式 Standby 】
- 实验所用硬件 --【STM32F407VE 开发板】
目录
[一、 STM32 三种低功耗模式 区别](#一、 STM32 三种低功耗模式 区别)
[1、睡眠模式 Sleep Mode](#1、睡眠模式 Sleep Mode)
[2、停止模式 Stop Mode](#2、停止模式 Stop Mode)
[三、Standby 待机模式 代码实现](#三、Standby 待机模式 代码实现)
[1. 进入 Standby 待机 模式](#1. 进入 Standby 待机 模式)
[2. 唤醒后的处理](#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中断回调函数的下方,添加函数。(按你所用中断回调函数位置而定)
cpp/****************************************************************************** * 函 数: 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(), 进入待机模式
cpp/* 判断复位来源 */ 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)。
文毕,欢迎指正、交流。~~