
STM32 低功耗共有三种模式Sleep 睡眠模式 、Stop 停止模式、Standby 待机模式。三种模式的 操作图解 地址【STM32 CubeMX】低功耗 -- Sleep 睡眠模式【STM32 CubeMX】低功耗 -- Stop 停止模式【STM32 CubeMX】低功耗 -- Standby 待机模式 【本文】本文将重点拆解Standby 待机模式的代码实现、关键事项 。参考资源Keil 工程下载 -- 【 STM32F407 -- 待机模式 Standby 】实验所用硬件 -- 【STM32F407VE 开发板】目录一、 STM32 三种低功耗模式 区别1、睡眠模式 Sleep Mode2、停止模式 Stop Mode二、工程准备1、基础工程2、烧录问题三、Standby 待机模式 代码实现1. 进入 Standby 待机 模式2. 唤醒后的处理四、 验证 测试五、常见问题 避坑指南一、 STM32 三种低功耗模式 区别1、睡眠模式 Sleep Mode功耗芯片工作电流约 10~20mA 参考值特点CPU暂停在SLEEP这一行外设正常工作唤醒时间极快;注意1能被所有中断事件唤醒若无法进入 SLEEP优先检查是否未关闭 SysTick 等频繁中断。注意2被中断唤醒后先进入对应中断函数执行完成后再运行 SLEEP 下一行代码。注意3SLEEP 模式无硬件唤醒标志唤醒后无需额外处理通常自定义软件标志配合业务逻辑。停止资源CPU内核停止运行、内核时钟关闭、程序暂停运行保持资源系统时钟、所有外设时钟保持运行GPIO 口状态保持运行时的电平内存、寄存器 数据保持不变唤醒方式任意中断事件均可唤醒 如 GPIO中断、Systick、UART、RTC 等)唤醒后程序正常运行无需重新初始化时钟 / 外设。适合场景短时间无需 CPU 运算但需要外设如串口、ADC、定时器持续工作的场景2、停止模式 Stop Mode功耗芯片工作电流约1mA参考值特点系统时钟关闭CPU和外设停止内存数据保持唤醒后仅需恢复系统时钟停止资源CPU 与所有外设停止工作内核时钟、外设时钟主时钟HSE/HSI被关闭外设停止工作保持资源低速时钟LSI/LSE用于 RTC继续运行内核1.8V供电保持内存、寄存器 数据保持不变GPIO 口状态保持运行时电平唤醒方式外部中断 EXTIRTC 闹钟唤醒后不需要重新初始化 UART、SPI、ADC等外设必须重新配置系统时钟如启用 HSE/PLL适合场景需要低功耗、同时要求快速唤醒、数据不丢失的场合。3、待机模式 Standby Mode功耗芯片工作电流约4uA参考值特点几乎断电内存数据丢失唤醒后相当于复位停止资源内核1.8V电源关闭内存、寄存器数据全部丢失内核与外设时钟关闭但 LSI/LSE 可在备份域继续给 RTC 供电IO 口变为高阻态模拟输入/浮空输入保持资源备份域Backup Domain备份寄存器、RTC 备份区域WAKEUP唤醒引脚 PA0RTC 相关引脚复位引脚唤醒方式WAKEUP 引脚PA0上升沿RTC 闹钟唤醒之后程序从 从头运行 相当于复位不会回到 Standby下一行)可通过 PWR_CSR 的 SBF / WUF 标志判断是 [待机唤醒] 还是 [上电复位]适合场景长时间休眠、对功耗要求极致的电池供电设备、遥测终端等注意 1 WAKEUP 引脚PA0仅在 Standby 模式下具备硬件自动唤醒功能Sleep / Stop 模式下 PA0 不具备此功能必须配置为EXTI 外部中断才能唤醒。注意 2 IWDG 独立看门狗只能复位芯片不能唤醒因为 IWDG 不会产生中断。二、工程准备1、基础工程三种低功耗模式均支持 RTC 闹钟唤醒因此统一使用 RTC 闹钟作为工程模板添加低功耗测试。不熟悉 RTC 闹钟的朋友参考教程图文教程 【 RTC 实时时钟 日历篇 】图文教程 【 RTC 实时时钟 闹钟篇 】本文所用工程模板【 Keil 工程文件 -- RTC 闹钟 】当然你可以使用自己的工程模板、需要的唤醒方式Sleep睡眠模式任意中断事件唤醒。Stop停止模式外部中断 EXTI 、RTC闹钟Standby待机模式WAKEUP 引脚 PA0 的上升沿 、 RTC 闹钟2、烧录问题STM32 进入 Stop、Standby 低功耗模式后芯片内核停止工作无法正常响应烧录信号可能出现无法下载、烧录失败的情况。以下是不同仿真器的解决方法STLink 仿真器的解决方法方法1按着板子复位按键不放手keil 点击 Load 后马上放开复位按键。利用复位后的空档期识别烧录信号。方法2BOOT0接线3.3V按一次复位按键烧录。拔掉BOOT0接线按一次复位按键即可。CMSIS-DAP 仿真器的解决方法Connect这一项选择 under Reset即可随时烧录。JLink 仿真器Stop 模式不影响随时可烧录。Standby 模式方法1按着板子复位按键不放手keil 点击 Load 后马上放开复位按键。利用复位后的空档期识别烧录信号。Standby 模式方法2BOOT0接线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。文毕欢迎指正、交流。~~