PWR
核心基础函数
C
// 1. 使能PWR时钟(所有模式必备)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
// 2. 核心低功耗指令
__WFI(); // Wait For Interrupt 等待中断唤醒
__WFE(); // Wait For Event 等待事件唤醒
一、睡眠模式(Sleep Mode)
模式特性
-
CPU 内核停止,外设时钟/寄存器/RAM 全部保持运行
-
功耗最低一档(快速唤醒),唤醒延迟 < 10μs
-
唤醒源:任意中断(EXTI、定时器、串口、RTC 等)
-
唤醒后直接继续执行代码,无需初始化
标准库配置代码
C
#include "stm32f10x.h"
// 配置外部中断 PA0 作为唤醒源(上升沿触发)
void SleepMode_Exit_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 1. 使能 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 2. 配置 PA0 为下拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 3. 配置 EXTI0 中断
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 4. 配置 NVIC 中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 进入睡眠模式
void Enter_SleepMode(void)
{
// 必备:使能PWR时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
// 配置唤醒中断
SleepMode_Exit_Init();
// 进入睡眠模式(内核停止,等待中断唤醒)
__WFI();
}
// 外部中断服务函数(唤醒后执行)
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
}
}
二、停止模式(Stop Mode)
模式特性
-
所有时钟关闭(CPU+外设全部停止)
-
RAM/寄存器数据保留,电压调节器可设低功耗
-
唤醒后系统时钟自动切为 HSI ,需重新配置系统时钟
-
唤醒源:EXTI 中断、RTC 闹钟、USB 唤醒等
标准库配置代码
C
// 配置 RTC 闹钟唤醒(停止模式最常用唤醒源)
void StopMode_RTC_Alarm_Init(void)
{
RTC_InitTypeDef RTC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 1. 使能备份域时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE); // 开启备份域访问
RCC_LSEConfig(RCC_LSE_ON); // 开启外部低速晶振 32.768kHz
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
// 2. RTC 时钟源选择 LSE
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
// 3. RTC 配置:1秒计数
RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
RTC_InitStructure.RTC_SynchPrediv = 0xFF;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
// 4. 配置闹钟:5秒后唤醒
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_Sub_Second, 5);
RTC_ITConfig(RTC_IT_ALR, ENABLE); // 使能闹钟中断
// 5. 配置 RTC 闹钟中断
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 进入停止模式
void Enter_StopMode(void)
{
// 1. 必备初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
StopMode_RTC_Alarm_Init();
// 2. 进入停止模式
// 参数1:低功耗调节器(更省电);参数2:WFI 中断唤醒
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// ===================== 唤醒后执行 =====================
// 关键:重新配置系统时钟(唤醒后时钟变为HSI,需切回72MHz)
SystemInit();
}
// RTC 闹钟中断服务函数
void RTCAlarm_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
{
RTC_ClearITPendingBit(RTC_IT_ALR);
}
}
三、待机模式(Standby Mode)
模式特性
-
1.8V 内核域完全断电(功耗最低,< 2μA)
-
RAM/寄存器数据全部丢失
-
唤醒后芯片复位(程序从 main 开头重新执行)
-
唤醒源:WKUP 引脚(PA0) 上升沿、RTC 闹钟、NRST 复位
标准库配置代码
C
// 进入待机模式(WKUP 引脚 PA0 上升沿唤醒)
void Enter_StandbyMode(void)
{
// 1. 必备:使能PWR+备份域时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE); // 开启备份域访问
// 2. 使能 WKUP 唤醒引脚(PA0)
PWR_WakeUpPinCmd(ENABLE);
// 3. 清除唤醒标志(必须!否则无法进入待机)
PWR_ClearFlag(PWR_FLAG_WU);
// 4. 进入待机模式
PWR_EnterSTANDBYMode();
}
三模式核心区别(标准库速记)
| 模式 | CPU | 时钟 | RAM | 唤醒后状态 | 标准库入口函数 |
|---|---|---|---|---|---|
| 睡眠模式 | 停止 | 运行 | 保留 | 继续执行 | __WFI() |
| 停止模式 | 停止 | 关闭 | 保留 | 重配时钟继续执行 | PWR_EnterSTOPMode() |
| 待机模式 | 断电 | 断电 | 丢失 | 芯片复位 | PWR_EnterSTANDBYMode() |
标准库必注意事项
- GPIO 省电配置
进入低功耗前,将不用的 GPIO 设为模拟输入,降低漏电流:
C
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- 停止模式唤醒
必须重新调用 SystemInit() 恢复 72MHz 系统时钟
- 待机模式
唤醒后程序从头运行,可用 备份寄存器(BKP) 保存关键数据
- 中断优先级
唤醒中断优先级必须高于主程序,否则无法唤醒