stm32-PWR、低功耗模式

PWR简介

低功耗模式说白了就是省电

结构

VDDA是模拟供电。VDD供电中电压调节器可以把电压降至1.8v,给1.8v供电区域供电,电压调节器就相当于1.8v区域的电源,电压低可以降低功耗。RCC是复位与时钟控制器,后备供电区域中RCC BDCR寄存器是RCC的寄存器,叫备份域控制寄存器,低电压检测器可以控制给后备区域的供电是VDD还是VBAT。

上电复位和掉电复位

当电压低于下限PDR时stm32复位,停止操作;高于上限POR时解除复位。上限和下限之间相差40mV,这是为了防抖。解除复位也有一个滞后时间,不会马上解除。阈值通常在1.9v左右。

可编程电压检测器PVD

PVD也是检测电压,上限和下限之间相差100mV。电压低于下限或高于上限时PVD可以申请中断提醒用户,PVD中断通道要借助外部中断EXTI,因为只有外部中断可以唤醒停止模式

低功耗模式

这三种低功耗模式,从上到下,越来越省电,关闭部分越来越多,越来越低功耗,但也越来越难唤醒;1.8v区域是芯片可以控制的,VDD区域的VDD是外部输入,芯片不能控制,只能控制其中晶振,后备区域更是独立。

睡眠模式

进入睡眠模式,需要通过调用WFI或者WFE,WFI就是等待中断,所以唤醒是通过中断唤醒;WFE就是等待事件,唤醒通过事件唤醒。关闭了1.8v区域的CPU时钟,但没有影响到其中的外设;对VDD区域没有影响;电压调节器是开启的,所以1.8v区域没有掉电,SRAM存储器和寄存器里的数据都还在。

停机模式

进入停机模式,配置PDDS位为0(PDDS=1表示待机模式),LPDS位配置电压调节器开启还是低功耗模式,配置SLEEPDEEP=1表示要进入深度睡眠,最后调用WFI或者WFE。选择WFI,则唤醒是通过外部中断的中断模式唤醒;选择WFE,则唤醒是通过外部中断的事件模式唤醒。停机模式关闭了1.8v区域的CPU和外设时钟,既然CPU和外设都关闭了,也就不需要VDD区域的HSI和HSE了,它们也关闭了。电压调节器是开启或者低功耗模式,区别就是低功耗模式更省电,唤醒时间更久,1.8v区域就没有掉电,数据都还在。但是LSI,LSE没有关闭,因为这是为RTC和看门狗准备的。

待机模式

进入待机模式,配置PDDS位=1,SLEEPDEEP位=1,调用WFI或者WFE。只能通过WKUP引脚上升沿、RTC闹钟、NRST引脚复位、和独立看门狗复位来唤醒。几乎能关闭的都关闭了,1.8v区域都关闭,VDD区域HSE,HSI关闭,电压调节器也关闭了,所以数据都清零了。

模式选择

WFI和WFE是最后选择,一旦执行后就会进入低功耗模式,所以图中寄存器配置都要在选择WFI,WFE之前进行。

三种模式细节

睡眠模式时电压调节器没有关闭,SRAM和寄存器数据都在,所以唤醒后程序会从暂停的地方开始运行。

停止模式时电压调节器也没有关闭,SRAM和寄存器数据都在,所以唤醒后程序也会从暂停地方开始运行。停止模式时HSI,HSE都被关闭,但在唤醒后不会主动开启HSE,会将HSI选为系统时钟,所以唤醒后系统主频就不是72MHZ,而是HSI的8MHZ,停止模式需要唤醒后手动开启HSE

待机模式时电压调节器关闭,SRAM数据丢失,所以唤醒后程序从头开始运行,从头开始程序会自动选择HSE。

如果正常模式下电流为50mA,那么睡眠模式下电流就是30mA,停止模式下为50uA,待机模式为5uA。

睡眠模式+串口接收数据代码

下位机等待上位机发送数据,可能偶尔才会发送,但需要程序一直运行一直等待,比较耗电。

低功耗模式中睡眠模式关闭了CPU时钟,程序停止运行,外设时钟没有关闭,USART依旧可以工作,能及时接收到数据,收到数据产生的中断也能唤醒睡眠模式。另外两个低功耗模式把外设时钟也关闭了,就收不到数据了,收到数据的中断也不能唤醒这两个模式,所以选择睡眠模式搭配串口接收数据。

主函数

uint8_t RXdata;
int main()
{
	OLED_Init();
	serial_init();
 while(1)
 {
	 RXdata=serial_receive();
	 serial_send(RXdata);
	 OLED_ShowHexNum(1,1,RXdata,2);
	OLED_ShowString(2,1,"running");
	 Delay_ms(100);
	 OLED_ShowString(2,1,"       ");
	 Delay_ms(100);
	  //睡眠模式选择WFI中断唤醒,还有两位SLEEPDEEP,SLEEPONEXTI需要用寄存器配置,这里不配置就使用默认值0,即立即睡眠

	 __WFI();

	 //上电程序运行到此就会进入睡眠,running不再显示,外设USART还在工作,接收到数据,产生中断唤醒后会先进入中断函数执行,然后才会继续从这里执行程序,接收数据,running显示一下,运行到此又进入睡眠
 }
}

停止模式+使用外部中断计次代码

主函数

//电平没有变化时程序依然在不断循环检测,running一直在显示。使用停止模式,running只在唤醒时显示,外部中断可以唤醒。外部中断是不需要时钟的。进入停止模式需要PWR

int main()
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	OLED_Init();
	countsensor_init();
	OLED_ShowString(1,1,"count:");
 while(1)
 {
	 OLED_ShowNum(1,7,countsensor_get(),4);
	 OLED_ShowString(2,1,"running");
	 Delay_ms(100);
	 OLED_ShowString(2,1,"       ");
	 Delay_ms(100);
	 
	 PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);//电压调节器开启,选择WFI。这个函数中已经配置好了SLEEPDEEP,PDDS和LPDS位。
	 //程序运行到此就进入了停止模式,产生外部中断时唤醒,进入中断函数执行后,回到这里继续向下执行程序,记一次数,显示一次running后又运行到此进入停止模式
	 
	 //注意第一次唤醒之后系统不会主动打开HSE时钟,而是选择了HSI时钟,所以之后running闪烁时间不对
	 SystemInit();//调用函数恢复使用HSE时钟
 }
}

待机模式+RTC闹钟、WKUP引脚代码

//RTC闹钟触发和WKUP引脚上升沿可以唤醒待机模式,进入待机模式需要PWR。

int main()
{
	OLED_Init();
	MYRTC_init();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	PWR_WakeUpPinCmd(ENABLE);//WKUP引脚在PA0,使能后强制为下拉输入,不需要初始化PA0口。WKUP引脚输入高电平一次也会唤醒一次。

	OLED_ShowString(1,1,"CNT:");//计数器值
	OLED_ShowString(2,1,"ALR:");//闹钟值
	uint32_t alarm=RTC_GetCounter()+10;
	RTC_SetAlarm(alarm);//设定闹钟值为当前计数值+10
 while(1)
 {
	 
	 OLED_ShowNum(2,5,alarm,10);
	 OLED_ShowNum(1,5,RTC_GetCounter(),10);
	 Delay_ms(500);
	 //stm32待机,如果外挂模块还在运行的话依然耗电,所以stm32待机前应该把能关闭的外挂模块都关闭
	 OLED_Clear();//以OLED为例,待机后清屏,只有唤醒后,程序从头开始运行后才会显示。

	 PWR_EnterSTANDBYMode();//进入待机模式,闹钟触发和WKUP引脚上升沿时会唤醒,程序从头开始执行。
	 //从头开始执行,程序会自动执行SystemInit()函数,选择HSE时钟,不需要像停止模式那种手动开启
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值