STM32学习——PWR电源控制:低功耗模式

PWR电源控制

PWR简介

PWR(Power Control)电源控制

PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能

可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务

低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时,降低STM32的功耗,延长设备使用时间,并且降低主频也可以省电

SYSCLK:系统主频,是36MHz,让某一个参数以1s为周期显示,但实际上是2s的周期,因为系统主频正常情况下是72MHz,降频到36MHz,所以运行时间就是原来的2倍

串口睡眠的目的:如果STM32一直没收到数据,主循环就会一直查询标志位,是无意义的耗电操作,不如进入睡眠,收到数据后,自动退出睡眠模式,执行一遍任务后,继续睡眠,这样在空闲时,一直睡眠,可以降低系统功耗。

注:在低功耗模式下,下载时候需要按住复位键,在点击下载按钮后0.2-0.3s内松开

电源框图

在这里插入图片描述
在这里插入图片描述

低功耗模式

在这里插入图片描述

从上到下,关闭的电路越来越多,功耗越来越低,同时越来越难唤醒

WFI:wait for Interrupt 等待中断,调用WFI进入的睡眠模式,任何外设发生任何中断时,芯片都会立刻醒来,因为中断发生,所以醒来之后的第一件事就是处理中断函数

WFE:Wait For Event 等待事件,唤醒条件为等待事件,事件可以是外部中断配置为事件模式,也可以是使能了中断,但是没有配置NVIC,调用WFE进入的睡眠模式,产生唤醒事件时会立刻醒来,醒来之后,一般不需要进中断函数,直接从睡的地方继续运行

模式选择

在这里插入图片描述

WFI和WFE指令是最终开启低功耗的触发条件,配置其他的寄存器,都要在这两个指令之前

一旦WFI或者WFE执行了,就会按照上面图示判断进入何种模式

睡眠模式特性

  • 执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
  • SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠
  • 在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态
  • WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
  • WFE指令进入睡眠模式,可被唤醒事件唤醒

停止模式特性

  • 执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
  • 1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来
  • 在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态
  • 当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟
  • 当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时
  • WFI指令进入停止模式,可被任意一个EXTI中断唤醒
  • WFE指令进入停止模式,可被任意一个EXTI事件唤醒

待机模式特性

  • 执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行
  • 整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电
  • 在待机模式下,所有的I/O引脚变为高阻态(浮空输入)
  • WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式

代码示例

代码1:修改主频

在这里插入图片描述

两个system文件,用来配置系统时钟,也就是配置RCC时钟树

修改只读文件夹

在这里插入图片描述
之后会直接定位到这个文件

在这里插入图片描述

然后右键-属性

在这里插入图片描述

去掉只读的对号即可

在这里插入图片描述

同时可以对整个文件夹的所有文件取消只读操作

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码文件:main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Delay.h"


int main(void)
{
	OLED_Init();
	
	OLED_ShowString(1,1,"SYSCLK:");
	OLED_ShowNum(1,8,SystemCoreClock,8);
	
	while(1)
	{
		OLED_ShowString(2,1,"Running");
		Delay_ms(500);
		OLED_ShowString(2,1,"		");
		Delay_ms(500);
	}
}

注:主频涉及一些精确的计时计算,一般情况下不推荐修改主频

代码2:睡眠模式串口发送接收

对于靠中断触发,没有中断就没有什么事的代码,就可以加入低功耗模式

代码文件:main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Serial.h"
#include "Delay.h"

uint8_t RxData;

int main(void)
{
	OLED_Init();
	Serial_Init();
	
	while(1)
	{
		if(Serial_GetRxFlag()==1)
		{
			RxData=Serial_GetRxData();
			OLED_ShowHexNum(1,1,RxData,2);
		}
		
		OLED_ShowString(2,1,"Running");
		Delay_ms(100);
		OLED_ShowString(2,1,"		");
		Delay_ms(100);
		
		//执行WFI之后,程序会立刻进入睡眠,程序在这里暂停。睡眠结束后,程序会在这里暂停的地方继续运行
		__WFI();
		//先进中断函数,再执行一遍程序功能
	}
}

代码3:停止模式+对射式红外传感器计次

停止模式只能能外部中断触发

相关函数:

void PWR_BackupAccessCmd(FunctionalState NewState);

使能后备区域的访问

void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel);

配置PVD的阈值电压

void PWR_PVDCmd(FunctionalState NewState);

使能PVD功能

void PWR_WakeUpPinCmd(FunctionalState NewState);

使能位于PA0位置的WKUP引脚

void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);

进入停止模式

void PWR_EnterSTANDBYMode(void);

进入待机模式

FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
void PWR_ClearFlag(uint32_t PWR_FLAG);

获取标志位和清除标志位的函数

代码文件:main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "CountSensor.h"
#include "Delay.h"

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	//开启PWR外设时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	
	OLED_ShowString(1,1,"Count:");

	while(1)
	{
		OLED_ShowNum(1,7,CountSensor_Get(),5);
		
		OLED_ShowString(2,1,"Running");
		Delay_ms(100);
		OLED_ShowString(2,1,"		");
		Delay_ms(100);
		
		PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);
		SystemInit();
	}
}

代码4:待机模式+实时时钟

代码文件:main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "MyRTC.h"
#include "Delay.h"

int main(void)
{
	OLED_Init();
	MyRTC_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	OLED_ShowString(1,1,"CNT:");//秒计数器
	OLED_ShowString(2,1,"ALR:");//闹钟值
	OLED_ShowString(3,1,"ALRF:");//闹钟标志位
	
	//WAKEUP引脚上升沿唤醒待机
	PWR_WakeUpPinCmd(ENABLE);
	
	uint32_t Alarm=RTC_GetCounter()+10;
	//设定闹钟,RTC_SetAlarm是只写的函数
	RTC_SetAlarm(Alarm);
	OLED_ShowNum(2,6,Alarm,10);
	
	while(1)
	{

		OLED_ShowNum(1,6,RTC_GetCounter(),10);
		OLED_ShowNum(1,6,RTC_GetFlagStatus(RTC_FLAG_ALR),1);
		
		OLED_ShowString(4,1,"Running");
		Delay_ms(100);
		OLED_ShowString(4,1,"		");
		Delay_ms(100);
		
		OLED_ShowString(4,9,"Running");
		Delay_ms(1000);
		OLED_ShowString(4,9,"		");
		Delay_ms(100);
		//进入待机模式
		
		OLED_Clear();
		
		PWR_EnterSTANDBYMode();
		//待机模式之后的代码执行不到
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值