理论
1.PWR简介
PWR(Power Control)电源控制
PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能
可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务
低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时,降低STM32的功耗,延长设备使用时间简介
2.电源框图
3.上电复位和掉电复位
4.可编程电压监测器
可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务
5.低功耗模式
(1)睡眠模式
进入方式:调用_WFI();或_WFE();进入睡眠模式
唤醒方式:有两种唤醒方式,WFI或WFE,常用的一种方式是中断(WFI)
作用:可以使CPU时钟进入睡眠模式,但是对其他的时钟没有影响,不会关闭震荡器,不会关闭电源,不会失去SARM相关的数据
**SLEEPONEXIT:**是否立即进入睡眠模式,0表示立即进入睡眠模式,1表示等待当前中断执行完进入睡眠模式
(2)停机模式
PDDS:用于选择进入停机模式还是待机模式,0表示进入停机模式,1表示进入待机模式
**LPDS:**设置电压调节器,0表示开启电压调节器,1表示开启低功耗模式
**SLEEPDEEP:**选择睡眠模式还是深度睡眠模式(待机/停机)
唤醒方式:任意外部中断
进入方式:对PDDS,LPDS,SLEEPDEEP,WFI进行配置
作用:可以保持RTC运行。看门狗的运行,不会失去SARM相关的数据
(3)待机模式
PDDS:用于选择进入停机模式还是待机模式,0表示进入停机模式,1表示进入待机模式
**SLEEPDEEP:**选择睡眠模式还是深度睡眠模式(待机/停机)
唤醒方式:WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式
进入方式:对PDDS,SLEEPDEEP,WFI进行配置
作用:只保留RTC与看门狗,不会丢失BKP的数据,会丢失SARM的数据
6.模式选择
执行WFI(Wait For Interrupt)或者WFE(Wait For Event)指令后,STM32进入低功耗模式
(1)睡眠模式
执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠
在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态
WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
WFE指令进入睡眠模式,可被唤醒事件唤醒
(2)停止模式
执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下
来
在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态
当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟(在进入停止模式后要在后面加上SystemInit();恢复主频72M)
当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时
WFI指令进入停止模式,可被任意一个EXTI中断唤醒
WFE指令进入停止模式,可被任意一个EXTI事件唤醒
(3)待机模式
执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行
整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电
在待机模式下,所有的I/O引脚变为高阻态(浮空输入)
WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式
API学习
1.SystemCoreClock
cpp
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/*
*当前的主频
*/
2.SystemInit
cpp
extern void SystemInit(void);
/*
* 初始化系统的硬件设置
*/
3.PWR_EnterSTANDBYMode
cpp
void PWR_EnterSTANDBYMode(void);
/*
*进入待机模式
*/
4.PWR_EnterSTOPMode
cpp
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);
/*
*停止模式的唤醒
*/
5.PWR_WakeUpPinCmd
cpp
void PWR_WakeUpPinCmd(FunctionalState NewState);
/*
*使能位于PA0的WKUP引脚,WKUP引脚上升沿唤醒待机模式
*/
6.RTC_SetAlarm
cpp
void RTC_SetAlarm(uint32_t AlarmValue);
/*
* 写入闹钟值到RTC的ALR寄存器
*/
代码
1.修改主频
main.c
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
int main(void)
{
OLED_Init(); //OLED初始化
OLED_ShowString(1, 1, "SYSCLK:"); //显示静态字符串
OLED_ShowNum(1, 8, SystemCoreClock, 8); //显示SystemCoreClock变量
//SystemCoreClock的值表示当前的系统主频频率
while (1)
{
OLED_ShowString(2, 1, "Running"); //闪烁Running,指示当前主循环运行的快慢
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(500);
}
}
2.睡眠模式
main.c
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
uint8_t RxData; //定义用于接收串口数据的变量
int main(void)
{
OLED_Init(); //OLED初始化
OLED_ShowString(1, 1, "RxData:"); //显示静态字符串
Serial_Init(); //串口初始化
while (1)
{
if (Serial_GetRxFlag() == 1) //检查串口接收数据的标志位
{
RxData = Serial_GetRxData(); //获取串口接收的数据
Serial_SendByte(RxData); //串口将收到的数据回传回去,用于测试
OLED_ShowHexNum(1, 8, RxData, 2); //显示串口接收的数据
}
OLED_ShowString(2, 1, "Running"); //OLED闪烁Running,指示当前主循环正在运行
Delay_ms(100);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
__WFI(); //执行WFI指令,CPU睡眠,并等待中断唤醒
}
}
3.停机模式
main.c
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
CountSensor_Init(); //计数传感器初始化
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //开启PWR的时钟
//停止模式和待机模式一定要记得开启
/*显示静态字符串*/
OLED_ShowString(1, 1, "Count:");
while (1)
{
OLED_ShowNum(1, 7, CountSensor_Get(), 5); //OLED不断刷新显示CountSensor_Get的返回值
OLED_ShowString(2, 1, "Running"); //OLED闪烁Running,指示当前主循环正在运行
Delay_ms(100);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); //STM32进入停止模式,并等待中断唤醒
SystemInit(); //唤醒后,要重新配置时钟
}
}
4.待机模式
main.c
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
MyRTC_Init(); //RTC初始化
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //开启PWR的时钟
//停止模式和待机模式一定要记得开启
/*显示静态字符串*/
OLED_ShowString(1, 1, "CNT :");
OLED_ShowString(2, 1, "ALR :");
OLED_ShowString(3, 1, "ALRF:");
/*使能WKUP引脚*/
PWR_WakeUpPinCmd(ENABLE); //使能位于PA0的WKUP引脚,WKUP引脚上升沿唤醒待机模式
/*设定闹钟*/
uint32_t Alarm = RTC_GetCounter() + 10; //闹钟为唤醒后当前时间的后10s
RTC_SetAlarm(Alarm); //写入闹钟值到RTC的ALR寄存器
OLED_ShowNum(2, 6, Alarm, 10); //显示闹钟值
while (1)
{
OLED_ShowNum(1, 6, RTC_GetCounter(), 10); //显示32位的秒计数器
OLED_ShowNum(3, 6, RTC_GetFlagStatus(RTC_FLAG_ALR), 1); //显示闹钟标志位
OLED_ShowString(4, 1, "Running"); //OLED闪烁Running,指示当前主循环正在运行
Delay_ms(100);
OLED_ShowString(4, 1, " ");
Delay_ms(100);
OLED_ShowString(4, 9, "STANDBY"); //OLED闪烁STANDBY,指示即将进入待机模式
Delay_ms(1000);
OLED_ShowString(4, 9, " ");
Delay_ms(100);
OLED_Clear(); //OLED清屏,模拟关闭外部所有的耗电设备,以达到极度省电
PWR_EnterSTANDBYMode(); //STM32进入停止模式,并等待指定的唤醒事件(WKUP上升沿或RTC闹钟)
/*待机模式唤醒后,程序会重头开始运行*/
}
}