STM32标准库——(19)PWR电源控制

目录

1.PWR简介

2.电源框图

3.上电复位和掉电复位

4.可编程电压检测器

5.低功耗模式

6.模式选择

​编辑

7.睡眠模式

8.停止模式

9.待机模式

10.修改主频

10.1 接线图

10.2 相关代码

11.睡眠模式+串口接送+接收

11.1 接线图

11.2 相关代码

12.停止模式+串口发送+接收

12.1 接线图

12.2 相关代码

12.2.1 相关API

12.2.2 main.c

13.待机模式+RTC实时时钟

13.1 接线图

13.2 相关代码

13.2.1 相关API

13.2.2 main.c


1.PWR简介

PWR属于外设部分 调用时需要先开启时钟

2.电源框图

  1.  这个图可以分为三个部分,最上面是模拟部分供电叫做VDDA,中间是数字部分供电,包括两块区域,VDD供电区域和1.8v供电区域,下面是后备供电,叫做VBAT
  2. VDDA供电区域,主要负责模拟部分的供电,其中包括AD转换器、温度传感器、复位模块、PLL锁相环,这些电路的供电正极是VDDA,负极是VSSA,其中AD转换器还有两个参考电压的供电脚,叫做VREF+和VREF-,这两个脚在引脚多的型号里会单独引出来,在引脚少的型号,比如我们这个C8T6,VREF+和VREF-在内部就已经分别接到了VDDA和VSSA了。

  3. 中间部分的供电,这一块由两部分组成,左边部分是VDD供电区域,其中包括IO电路、待机电路、唤醒逻辑和独立看门狗右边部分是VDD通过电压调节器降压到1.8V,提供给后面这一块的1.8V供电区域1.8V区域包括CPU核心、存储器和内置数字外设,可以看出来STM32内部的大部分关键电路,CPU、存储器和外设其实都是以1.8V的低电压运行的,当这些外设需要与外界进行交流时,才会通过IO电路转换到3.3V,所以我们从外部看,好像STM32内部全是3.3V,但实际上它内部的CPU、外设等都是以1.8V供电运行,使用低电压运行的主要目的是降低功耗,电压越低内部电路运行的功耗就相对越低

  4. 电压调节器,它的作用是给1.8V区供电,因为我们后面会提到这个1.8V区域和电压调节器,最下面就是我们上一节提到的VBAT后备供电区域了,其中包括LSE 32K晶体振荡器、后备寄存器、RCC BDCR计寄存器和RTCRCC BDCR是RTC的寄存器,叫做备份域控制寄存器,也是和后备区域有关的寄存器,所以也可以有VBAT供电,然后这里有个低电压检测器,可以控制这个开关VDD有电时由VDD供电,VDD没电时由VBAT供电

3.上电复位和掉电复位

当VDD或者VDDA电压过低时,内部电路直接产生复位,让STM32复位住不要乱操作,这个复位和不复位的界限之间,设置了一个40毫伏的迟滞电压,大于上限POR(Power On Reset)时解除复位,小于下限PDR(Power Down Reset)时复位,这是一个典型的迟滞比较器,设置两个阈值的作用,就是防止电压在某个阈值附近波动时,造成输出也来回抖动,下面的复位信号reset是低电平有效的,所以在前面和后面电压过低时是复位的,中间电压正常的时候不复位

STM32数据手册,在5.3.3内嵌复位和电源控制模块特性里有这个表,这里写了上电或掉电复位阈值,下降沿,也就是PDR掉电复位的阈值下限,典型值是1.88V,上升沿,也就是POR上电复位的阈值上限,典型值是1.92V1.92-1.88就是迟滞的阈值40毫伏,所以如果忽略迟滞的话,简单来说就是大于1.9V上电,低于1.9V掉电,然后最后一行就是TRSTTEMPO,复位持续时间,典型值是2.5ms

4.可编程电压检测器

可编程电压监测器,简称PVD,他的工作流程和上面差不多都是监测VDD和VDDA的供电电压,但是PVD的区别就是,首先它这个阈值电压是可以使用程序指定的可以自定义调节,调节的范围可以看一下数据手册,在这个表的上面就是PVD的阈值,配置PLS寄存器的3个位可以选择右边这么多的阈值,因为这里也同样是迟滞比较,所以有两个阈值,可选范围是2.2V到2.9V左右PVD上限和下限之间的迟滞电压是100毫伏,可以看到PVD的电压是比上电掉电复位的电压要高的,画个图就是3.3伏是正常的供电,当这个电压降低在2.9伏到2.2伏之间属于PVD监测的范围可以通过PVD设置一个警告线,之后再降低到1.9伏,就是复位电路的检测范围,低于1.9伏直接复位住不让动,就是这两个电压监测的工作任务,那当然PVD触发之后,芯片还是能正常工作的,只不过是电源电压过低,该提醒一下用户了,所以看一下下面这个PVD输出,这个是正逻辑,电压过低时为1,电压正常值为0,这个信号可申请中断在上升沿或者下降沿时触发中断,一是提醒程序进行适当的处理,另外这个PVD的中断申请,是通过外部中断实现的,我们可以看一下外部中断这一节,这个图(EXTI基本结构图)可以看到PVD输出的信号是跑到这里来了,所以如果要使用PVD的话,记得要配置外部中断,然后下面这里还有RTC(EXTI基本结构图),这个是RTC的闹钟信号,也有接到外部中断,其实RTC自己是有中断的,那为啥还要借到外部中断,这个等会就知道了,因为低功耗模式设计的是,只有外部中断可以唤醒停止模式,其他这些设备也想唤醒停止模式的话,都可以通过借道外部中断来实现,其实后面这两个USB和ETH,也都只有他们的wake up唤醒信号接过来了,目的也是为了唤醒停止模式,这个了解一下。

5.低功耗模式

  1. 睡眠模式,这是浅睡眠,这里写了直接调用WFI或者WFE即可进入,这两个东西是内核的指令,对应库函数里也有对应的函数,直接调用函数即可,其中WFI的意思是wait for interrupt等待中断,意思就是我先睡了,如果有中断发生的话再叫我起来,所以对应的唤醒条件是任意中断调用WFI进入的睡眠模式,任何外设发生任何中断时,芯片都会立刻醒来,因为中断发生了,醒来之后的第一件事一般就是处理中断函数,然后下面WFE意思是wait for event等待事件,对应的唤醒条件是唤醒事件这个事件可以是外部中断配置为事件模式,也可以是使能了中断,但是没有配置NVIC,调用WFE进入的睡眠模式,产生唤醒事件时会立刻醒来,醒来之后一般不需要进中断函数,直接从睡的地方继续运行,这是WFI和WFE的作用,相同点是调用任意一个之后,芯片都进入睡眠,不同点是WFI进入的得用中断唤醒,WFE进入的得用事件唤醒,最后看一下睡眠模式对电路的影响,对1.8V区域时钟的影响是CPU时钟关,对其他时钟和ADC时钟无影响,对VDD区域时钟的影响是无,对电压调节器的操作是开,所以睡眠模式对电路的影响就是,只把CPU时钟关了,对其他电路没有任何操作CPU时钟关了,程序就会暂停,不会继续运行了,CPU不运行芯片功耗就会降低,另外这里还可以看出,关闭电路通常有两个做法,一个是关闭时钟,另一个是关闭电源关闭时钟,所有的运算和涉及时序的操作都会暂停,但是寄存器和存储器里面保存的数据还可以维持不会消失,关闭电源就是电路直接断电,电路的操作和数据都会直接丢失,所以关闭电源比关闭时钟更省电

  2. 停机模式,首先sleepdeep位设置为1告诉CPU你可以放心的睡进入深度睡眠模式,另外PDDS这一位用来区分它是停机模式,还是下面的待机模式,PDDS等于0进入停机模式,PDDS等于1进入待机模式,之后LPDS用来设置最后这个电压调节器,是开启还是进入低功耗模式,RPDS等于0电压调节器开启,RPDS等于1电压调节器进入低功耗,最后当我们把这些位提前设置好了,最后再调用WFA或者WFE,芯片就可以进入停止模式了,然后停止模式的唤醒,因为这个模式下芯片睡得更深,关的东西更多,所以唤醒条件就苛刻一些,是任一外部中断,刚才睡眠模式是任一中断,所有外设的中断都行,现在停止模式,要求就是只有外部中断才能唤醒,其他中断唤醒不了,刚才我们还提到了,PVD、RTC闹钟、USB唤醒、ETH唤醒借道了外部中断,所以这四个信号也可以唤醒停止模式,因为这里并没有区分WFI和WFE,其实也可以想象得到,WFI要用外部中断的中断模式唤醒,WFE要用外部中断的事件模式唤醒,这是对应的,最后看停止模式对电路有哪些操作呢,首先关闭所有1.8伏区域的时钟,这意思就是不仅CPU不能运行,外设也运行不了,定时器在定时的会暂停,串口收发数据也会暂停,不过由于没关闭电源,所以CPU和外设的寄存器数据都是维持原状的,之后下一个HSI和HSE的振荡器关闭,既然CPU和外设时钟都关了,那这两个高速时钟显然也没用了,所以HSI内部高速时钟和HSE外部高速时钟会关闭,当然他没提到的,LSI内部低速时钟和LSE外部低速时钟,这两个并不会主动关闭,如果开启过这两个时钟还可以继续运行,最后电压调节器,这里可以选择是开启或者处于低功耗模式,刚才说了,这个电压调节器是由这个LPDS位控制的,这个开启和低功耗模式有啥区别呢,其实区别也不大,电压调节器无论是开启还是低功耗,都可以维持1.8伏区域寄存器和存储器的数据内容,区别就是低功耗模式更省电一些,同时低功耗模式在唤醒时要花更多的时间,相反电压调压器开启的话就是更耗电一些唤醒更快了,那这些就是停止模式的介绍,主要操作就是把运行的高速时钟都关了,CPU和外设都暂停工作,但是电压调节器并没有关,存储器和寄存器数据可以维持原样,它的唤醒条件比较苛刻,只能通过外部中断唤醒。

  3. 待机模式,和停机模式差不多,首先sleepdeep也是置1即将深度睡眠,然后PDDS置1表示即将进入待机模式最后调用WFI或者WFE就可以进入待机模式了,然后看一下唤醒条件,普通外设的中断和外部中断都无法唤醒待机模式,待机模式只有这几个指定的信号才能唤醒第一个是wake up引脚的上升沿,wake up引脚,可以看一下引脚定义,这里PA0-WKUP指示了引脚的位置,就是PA0的位置,第二个是RTC闹钟事件,这个我们的示例代码和上一节RTC提到过,RTC闹钟可以唤醒待机模式,应用场景就是芯片每隔一段时间自动工作一次,第三个是NRST引脚上的外部复位,意思就是按一下复位键,它也是能唤醒的,最后一个IWDG独立看门狗复位,这个了解一下就行了,看门狗我们最后介绍,可以看出待机模式,只有这指定的四个信号能唤醒,其他信号都唤醒不了,唤醒条件最为苛刻,之后待机模式对电路的操作基本上是能关的全都关了,1.8伏区域的时钟关闭,两个高速时钟关闭,电压调节器关闭,这意味着1.8伏区域的电源关闭,内部的存储器和寄存器的数据全部丢失但是和停止模式一样,它并不会主动关闭LSI和LSE两个低速时钟,因为这两个时钟还要维持RTC和独立看门狗的运行,所以不会关闭

6.模式选择

7.睡眠模式

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

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

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

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

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

8.停止模式

•执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行

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

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

•当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟

•当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时

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

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

9.待机模式

•执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行

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

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

WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式

10.修改主频

10.1 接线图

10.2 相关代码

main.c

#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);
	}
}

system_stm32f10x.c中SystemCoreClock函数的定义主频部分 修改成其他M数 OLED显示屏第一行会显示对应主频数的八位格式 第二行的Running频率也会发生改变 一开始是72M 对应的就是1s 因为Delay.c中定义的就是72M 所以周期就为1s 像上述代码是36M 主频变为原来的一半 则周期为2s。

11.睡眠模式+串口接送+接收

11.1 接线图

11.2 相关代码

main.c

#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睡眠,并等待中断唤醒
	}
}

调用WFI()函数可以实现睡眠模式 当while循环执行到WFI() 函数进入睡眠模式 用串口助手发送数据时 USART外设接收到数据 产生中断 唤醒CPU 睡眠模式唤醒之后 在暂停的地方继续运行 所以程序会运行到WIF之后 程序回到while循环开头之前 先进入USART中断函数 在中断函数里读取数据 置RxFlag 清除RXNE 之后回到主循环 这时RxFlag置1 便继续执行下面程序 进行数据回传 所以每发送一次数据 OLED显示数据一次Running 同时RxData显示发送数据

12.停止模式+串口发送+接收

12.1 接线图

12.2 相关代码

12.2.1 相关API

 PWR_EnterSTOPMode

/**
  * @brief  Enters STOP mode.
  * @param  PWR_Regulator: specifies the regulator state in STOP mode.
  *   This parameter can be one of the following values:
  *     @arg PWR_Regulator_ON: STOP mode with regulator ON
  *     @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode
  * @param  PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.
  *   This parameter can be one of the following values:
  *     @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction
  *     @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction
  * @retval None
  */
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
功能:
	进入停止(STOP)模式
参数:
	PWR_Regulator: 电压转换器在停止模式下的状态
	PWR_STOPEntry: 选择使用指令 WFE 还是 WFI 来进入停止模式
返回值:
	无      

第一步先读取PWR_CR寄存器 放在临时变量中 第二步清除PDDS和LPDS位 清除PDDS位代表PDDS=0 对应6.模式选择图中停止模式的选择部分 第三步根据指定参数设置LPDS位 若选择调压器开启 这里LPDS=0 若选择调压器低功耗 则LPDS=1 第四步将临时变量写入PWR_CR寄存器 参数生效 最后设置内核的SLEEPDEEP位 其中|=SLEEPDEEP的掩码表示把SLEEPDEEP置1 即进入深度睡眠模式 程序最后是一个if判断 如果第二个参数是WFI 则执行WFI指令 否则执行WFE指令 停止模式唤醒之后 最底下程序会把SLEEPDEEP位清0

12.2.2 main.c
#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();										//唤醒后,要重新配置时钟
                                                            //按下复位显示Running时间很快,而红外模块计次时Running闪烁慢,唤醒后会自动配置HSI位系统时钟,原来的是72M,现在HSI是8M,若不重新配置,则复位后就是8M,显示时间长
	}
}

13.待机模式+RTC实时时钟

13.1 接线图

13.2 相关代码

13.2.1 相关API

PWR_EnterSTANDBYMode

/**
  * @brief  Enters STANDBY mode.
  * @param  None
  * @retval None
  */
void PWR_EnterSTANDBYMode(void)
功能:
	进入待机(STANDBY)模式
参数:
    无
返回值:
    无

第一步清除WakeUp标志位 第二部选择STANDBY模式 实际上就是把PDDS置1 表示进入待机模式 第三步把SLEEPDEEP置1 进入深度睡眠 最后一步调用WFI指令

PWR_WakeUpPinCmd

/**
  * @brief  Enables or disables the WakeUp Pin functionality.
  * @param  NewState: new state of the WakeUp Pin functionality.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void PWR_WakeUpPinCmd(FunctionalState NewState)
功能:
	使能或者失能唤醒管脚功能
参数:
	NewState: 唤醒管脚功能的新状态,这个参数可以取:ENABLE 或者 DISABLE
返回值:  
    无
13.2.2 main.c
#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);		//显示闹钟标志位 当计时值等于闹钟值 标志位值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闹钟)
		/*待机模式唤醒后,程序会重头开始运行*/
	}
}
  • 20
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值