PWR和低功耗模式
PWR简介
- PWR(Power Control) 电源控制
- PWR负责管理STM32内部的电源供电部分,可以实现可编程电压检测器和低功耗模式的功能
- 可编程电压检测器(PVD) 可以监控VDD电源电压,当VDD下降到PVD阈值以下或上升到PVD阈值之上时,PVD会触发中断,用于执行紧急关闭任务
- 低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时,降低STM32的功耗,延长设备使用时间
电源框图
- V D D 、 V S S V_{DD}、V_{SS} VDD、VSS给数字电路供电
- V D D A 、 V S S A V_{DDA}、V_{SSA} VDDA、VSSA给模拟电路供电
- 低电压检测器在检测到 V D D 和 V S S V_{DD}和V_{SS} VDD和VSS之间电压低于阈值后,会切换后备供电区域的供电电源为 V B A T V_{BAT} VBAT,而当 V D D 和 V S S V_{DD}和V_{SS} VDD和VSS供电正常时,则由 V D D 和 V S S V_{DD}和V_{SS} VDD和VSS供电
- 芯片内部的数字电路(1.8V供电区域)供电电压为1.8V
- 关于 V D D A 和 V S S A V_{DDA}和V_{SSA} VDDA和VSSA的作用参考手册, 注意在STM32F103C8T6中未引出
上电复位和掉电复位
可编程电压检测器
低功耗模式
- 一般使用
WFI (wait for interrupt)
等待中断 睡眠模式(Sleep Mode)
下, 任一中断都可以唤醒MCU,一般省电停机模式(Stop Mode)
下,仅外部中断 能够唤醒MCU,同时1.8V区域的时钟全部关闭,HSI和HSE的时钟也关闭,但电压调节器仍然打开,SRAM和寄存器中的数据不会丢失待机模式(Standby Mode)
下,仅特定事件能够唤醒MCU,相较于停机模式
电压调节器关闭,SRAM和寄存器中数据丢失Sleep Mode
和Stop Mode
唤醒后程序从进入低功耗模式的代码开始重新执行,而Standby Mode
唤醒后程序从头开始执行(因为数据都丢失了)- 值的注意的是,
Stop Mode
唤醒后默认使用HSI (8MHz)
作为系统时钟, 若想用HSE
则需重新调用SystemInit()
函数
模式选择
- 对照该图和参考手册配置自己需要的模式
睡眠模式
-
执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
-
SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠 (WFI或WFE写主函数里立刻进入睡眠还是先处理中断差别不大)
-
在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态 (为进一步降低能耗,在执行WFI/WFE前关闭能关闭的外设)
-
WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
-
WFE指令进入睡眠模式,可被唤醒事件唤醒
停止模式
-
执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
-
1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来
-
在停止模式下,所有的I/ O引脚都保持它们在运行模式时的状态 (为进一步降低能耗,在执行WFI/WFE前关闭能关闭的外设)
-
当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟
-
当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时
-
WFI指令进入停止模式,可被任意一个EXTI中断唤醒 (RTC和PVD可借道EXTI中断通道将MCU从停止模式唤醒)
待机模式
-
执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行
-
整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电
-
在待机模式下,所有的I/O引脚变为高阻态(浮空输入)(不用手动关闭外设)
-
WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式
降低系统主频和关闭APB和AHB总线上未被使用的外设时钟
- 除了低功耗模式能降低电源消耗外,降低系统主频和关闭未使用的外设时钟也是降低电源消耗的很好的方式
- 系统主频通过时钟树可以看出,由
HSE
接外部晶振提供(一般8MHz),经过PLL
得到倍频,然后作为系统主频
-
关于系统主频的修改,相关的文件是
system_stm32f10x.c
,通过宏定义可修改成以下时钟频率, 具体函数的执行流程可以自己看或看江科大的视频
-
如何取消只读文件的限制
打开文件属性,取消可读后确定
文件上的钥匙消失,现在可以修改文件中关于主频的宏定义
主要代码
功能为单片机运行10s即进入停止模式, 当检测到外部中断后, 退出停止模式, 运行10s后再次进入停止模式
main.c
c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"
#include "key.h"
#include "LED.h"
#include "Timer.h"
#include "valve.h"
uint8_t Stop_Time;
int main(void)
{
OLED_Init();
MyRTC_Init(); // RTC初始化
Key_Init(); // 按键初始化
LED_Init(); // LED 初始化
Timer_TIM3_Init(); // 定时器初始化
Valve_Init(); // 电磁阀端口初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // 打开PWR时钟 *
OLED_ShowString(1, 1, "Date:XXXX-XX-XX");
OLED_ShowString(2, 1, "Time:XX:XX:XX");
Stop_Time = 0;
while (1)
{
MyRTC_ReadTime();
OLED_ShowNum(1, 6, MyRTC_Time[0], 4);
OLED_ShowNum(1, 11, MyRTC_Time[1], 2);
OLED_ShowNum(1, 14, MyRTC_Time[2], 2);
OLED_ShowNum(2, 6, MyRTC_Time[3], 2);
OLED_ShowNum(2, 9, MyRTC_Time[4], 2);
OLED_ShowNum(2, 12, MyRTC_Time[5], 2);
OLED_ShowNum(3, 1, Stop_Time, 3);
if(Stop_Time > 100)
{
Stop_Time = 0;
OLED_Clear(); // 屏幕熄灭
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, DISABLE); // 关闭GPIOB时钟
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); // 进入停止模式*
SystemInit(); // 重新设置时钟
OLED_Init();
Valve_Init(); // 电磁阀端口初始化
OLED_ShowString(1, 1, "Date:XXXX-XX-XX");
OLED_ShowString(2, 1, "Time:XX:XX:XX");
}
}
}
/**
* @brief 按键中断服务函数 PA8
*/
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetFlagStatus(EXTI_Line8))
{
Delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 0)
{
LED_Turn();
}
EXTI_ClearITPendingBit(EXTI_Line8);
}
}
/**
* @brief 定时器中断服务函数 TIM3_UpDate
*/
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update))
{
Stop_Time += 1;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
- 要进入停止模式只需通过
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
打开PWR时钟 - 再在需要进入停止模式的时候调用
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
即可进入停止模式 - 进入停止模式前,根据需求关闭耗电的外设
- 从停止模式退出后,系统使用HSI时钟主频默认为
8Mhz
, 需重新调用SystemInit()
函数重新设置时钟为HSE使主频恢复为72MHz
- 从停止模式退出后,应重新初始化关闭的外设
效果展示
参考资料
模式退出后,系统使用HSI时钟主频默认为8Mhz
, 需重新调用SystemInit()
函数重新设置时钟为HSE使主频恢复为72MHz
- 从停止模式退出后,应重新初始化关闭的外设