STM32入门教程(PWR电源控制篇)

参考教程:[13-1] PWR电源控制_哔哩哔哩_bilibili

1、PWR(Power Control)电源控制:

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

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

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

2、电源框图:

(1)VDDA供电区域是模拟供电区域(其中A/D转换器还有两个提供参考电压的引脚VREF);VDD供电区域和1.8V供电区域是数字供电区域,cpu核心、存储器和内置数字外设属于1.8V供电区域,1.8V电压由电压调节器提供,提供较低电压的目的是为了降低功耗。

(2)后备供电区域前有一个低电压检测器控制VBAT的开关,当VDD通电时后备供电区域由VDD供电,当VDD没有通电时后备供电区域由VBAT供电(RTC时钟源选择LSE的话,当VDD掉电时,RTC和LSE由VBAT供电,RTC仍能正常工作)。

3、上电复位和掉电复位:

当VDD或者VDDA过低时,内部电路直接产生复位信号(低电平有效),是否产生复位信号的界限之间有40mV的迟滞电压,电压从低到高时需要高于上限POR(Power On Reset)才会解除复位,电压从高到低时需要低于下限PDR(Power Down Reset)才会复位,这是为了防止电压在某个阈值附近抖动从而造成复位信号的抖动。

4、可编程电压监测器:

PVD输出的上升沿或下降沿可以触发中断(通过外部中断实现),另外与“上电复位和掉电复位”不同的是,PVD阈值可以通过程序进行设定。

5、低功耗模式:

6、模式选择:执行WFI(Wait For Interrupt)或者WFE(Wait For Event)指令后,STM32进入低功耗模式

(1)睡眠模式:

如果SLEEPDEEP=0,执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行

②SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠。

③在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态

WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒

WFE指令进入睡眠模式,可被唤醒事件唤醒

(2)停机模式:

如果SLEEPDEEP=1、PDDS=0,执行完WFI/WFE指令后,STM32进入停机模式,程序暂停运行,唤醒后程序从暂停的地方继续运行

②如果LPDS=0,停机模式下电压调节器开启;如果LPDS=1,停机模式下电压调节器处于低功耗状态(更省电,但是唤醒延迟更高)。

1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来

④在停机模式下,所有的I/O引脚都保持它们在运行模式时的状态

当一个中断或唤醒事件导致退出停机模式时,HSI被选为系统时钟(唤醒STM32后需要将系统时钟选择回HSE,以配置主频为原本的72MHz)

WFI指令进入停机模式,可被任意一个EXTI中断唤醒

WFE指令进入停止模式,可被任意一个EXTI事件唤醒

(3)待机模式:

如果SLEEPDEEP=1、PDDS=1,执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行

整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电

在待机模式下,所有的I/O引脚变为高阻态(浮空输入)

WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位,四个条件满足其中一个,退出待机模式

7、修改主频:

(1)按照下图所示接好电路,并将OLED显示屏的项目文件夹复制一份作为模板使用。

(2)system_stm32f10x.h文件和system_stm32f10x.c文件用于配置RCC时钟树,如果想要修改系统主频,可以在system_stm32f10x.c文件中找到红框所在位置,目前蓝框框选的就是配置系统主频为72MHz的宏定义,将该宏定义注释后解除橙框内的其中一个宏定义就可修改主频。(F103C8T6是MD、中容量、非超值系列,图中107、108两行代码在预编译的时候会被移除,不用理会)

(3)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中观察OLED屏的显示。(需要更改系统主频,反复编译,对比修改主频前后的区别)

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

int main()
{
	OLED_Init();
	
	OLED_ShowString(1,1,"SYSCLK:");
	OLED_ShowNum(1,8,SystemCoreClock,8);  //显示当前主频
	
	while(1)
	{
		//闪烁显示
		OLED_ShowString(2,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(2,1,"       ");
		Delay_ms(500);  //500个时间单位
	}
}

8、模式选择睡眠模式:

(1)按照下图所示接好电路,并将串口发送+接收的项目文件夹复制一份作为模板使用。

(2)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中进行调试,使用串口助手向单片机发送数据,每发送一次数据,OLED屏闪烁显示一次“Running”。

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

uint8_t RxData ;

int main()
{
	OLED_Init();
	Serial_Init();
	
	OLED_ShowString(1, 1, "RxData:");
	
	while(1)
	{
		if(Serial_GetRxFlag() == 1)  //判断是否有新数据到来
		{
			RxData = Serial_GetRxData();  //把接收的新数据拷贝到RxData中
			Serial_SendByte(RxData);      //把接收到的数据传给电脑
			//(调试时注意选择HEX模式进行发送和接收)
			OLED_ShowHexNum(1, 8, RxData, 2);
		}
		OLED_ShowString(2,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(2,1,"       ");
		Delay_ms(500);  //500个时间单位
		
		__WFI();   //进入睡眠模式(中断唤醒)
		//默认SLEEPDEEP=0(立刻睡眠)
	}
}

(3)程序解释:将程序下载到开发板后,程序很快来到“__WFI();”,这时STM32进入睡眠模式,程序停止运行,如果使用串口助手向STM32发送数据,那么就会触发一次中断,STM32从睡眠模式中被唤醒,首先会执行串口的中断函数完成数据的接收,接着程序从“__WFI();”语句的下一步——判断是否有新数据到来开始执行,本例中100%有新数据到来,所以OLED屏会显示刚刚发送的HEX格式数据,接着“Running”闪烁显示1次,程序来到“__WFI();”,再次进入睡眠模式。

9、模式选择停机模式:

(1)按照下图所示接好电路,并将对射式红外传感器计次的项目文件夹复制一份作为模板使用。

(2)在stm32f10x_pwr.h文件中有PWR模块相关的函数。

[1]PWR_DeInit函数:恢复缺省配置。

[2]PWR_BackupAccessCmd函数:使能对后备区域的访问。

[3]PWR_PVDCmd函数:使能PVD输出。

[4]PWR_PVDLevelConfig函数:配置PVD的阈值电压。

[5]PWR_WakeUpPinCmd函数:使能位于PA0位置的WKUP引脚(配合待机模式使用)。

[6]PWR_EnterSTOPMode函数:使STM32进入停止模式。

[7]PWR_EnterSTANDBYMode函数:使STM32进入待机模式。

[8]PWR_GetFlagStatus函数:获取标志位。

[9]PWR_ClearFlag函数:清除标志位。

(3)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中进行调试。(每挡一次光就产生一次外部中断STM32就会从停机模式中被唤醒,处理完中断后程序从“SystemInit();”语句开始执行)

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

int main()
{
	OLED_Init();
	CountSensor_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  //开启PWR的时钟
	
	OLED_ShowString(1,3,"Count:"); 
	
	while(1)
	{
		OLED_ShowNum(2,3,CountSensor_Get(),3);  //显示挡光次数
		
		OLED_ShowString(3,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(3,1,"       ");
		
		PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);  //进入停机模式
		//PWR_Regulator_ON:电压调节器开启
		//PWR_STOPEntry_WFI:可被任意一个EXTI中断唤醒
		
		//唤醒STM32后需要将系统时钟选择回HSE
		SystemInit();
	}
}

10、模式选择待机模式:

(1)按照下图所示接好电路,并将实时时钟的项目文件夹复制一份作为模板使用。

(2)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中进行调试。

闹钟事件会在程序下载完成后的第10秒发生,这时STM32从待机模式中被唤醒,由于RTC在程序刚下载完成时已经初始化过一次,所以不会再进行初始化,计时不会被重置,但是闹钟会被重新设定为当前时间戳的后10秒,然后再次进入待机模式,以此往复,也就是说每隔10秒STM32就会被唤醒一次

使用导线给PA0提供上升沿,WKUP引脚的上升沿可以使STM32退出待机模式,这跟闹钟事件无关,不过闹钟还是会被重新设定为当前时间戳的后10秒,然后再次进入待机模式。

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

int main()
{
	OLED_Init();
	MyRTC_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  //开启PWR的时钟
	
	OLED_ShowString(1, 1, "CNT:");
	OLED_ShowString(2, 1, "ALR:");
	OLED_ShowString(3, 1, "ALRF:");
	
	PWR_WakeUpPinCmd(ENABLE);  //使能位于PA0位置的WKUP引脚(本例需要WKUP引脚产生上升沿)
	
	//闹钟定时在当前时间戳后10秒
	uint32_t Alarm = RTC_GetCounter() + 10;
	RTC_SetAlarm(Alarm);
	
	while(1)
	{		
		OLED_ShowNum(1,6,RTC_GetCounter(),10);
		OLED_ShowNum(2,6,Alarm,10);
		OLED_ShowNum(3,6,RTC_GetFlagStatus(RTC_FLAG_ALR),1);  //闹钟标志位:闹钟响时该位置1
		
		OLED_ShowString(4,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(4,1,"       ");
		Delay_ms(500);  //500个时间单位
		
		OLED_ShowString(4,9,"STANDBY");
		Delay_ms(1000);  //500个时间单位
		OLED_ShowString(4,9,"       ");
		Delay_ms(100);  //500个时间单位
		
		OLED_Clear();  //清屏
		
		PWR_EnterSTANDBYMode();   //进入待机模式
		//(本例中闹钟事件上升沿/WKUP引脚的上升沿可以退出待机模式,程序从头开始执行)
	}
}

猜你喜欢

转载自blog.csdn.net/Zevalin/article/details/134796335