STM32 PWR电源控制:睡眠、停止和待机模式详解

图文概述:

 

!!!!!!!!注意!!!!!!!!!

每次使用 __WFI()指令或__WFE()指令编程下载后,如需要重新下载其他程序则需要退出睡眠模式,而此时的下载操作为:按住复位键不松手,点击下载程序,然后松手,即可下载新的程序到单片机中.

睡眠模式:

代码:

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

/*
在串口通信中,先执行一遍"Running"闪烁后,通过__WFI()指令CPU进入睡眠模式
且等待任一中断唤醒,所以当串口发送数据后会进入USART1通道的中断函数中,
此时唤醒CPU并继续while循环,直到遇见__WFI()指令后继续等待中断唤醒
---睡眠模式可节省耗电---	
*/

uint8_t RxData;

int main(void)
{
	OLED_Init();
	Serial_Init();

	OLED_ShowString(1, 1, "RxData:");
	
	
	while(1)
	{
		if(Serial_GetRxFlag() == 1)
		{
			RxData = Serial_GetRxData();
			Serial_SendByte(RxData);     //将数据传给发送区,让串口助手接收到
			OLED_ShowHexNum(1, 8, RxData, 2);
		}
		
		OLED_ShowString(2, 1, "Running");
		Delay_ms(100);
		OLED_ShowString(2, 1, "       ");
		Delay_ms(100);
		
		__WFI(); //CPU进入睡眠模式并且等待中断唤醒
		
	}
}


关键代码:

		__WFI(); //CPU进入睡眠模式并且等待中断唤醒

具体操作对应下图:

 

停止模式:

代码:

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

/*
  本实验的目的---在停止模式下进行对射式红外传感器计次.
  通过开启PWR的外设时钟+配置PWR_EnterSTOPMode函数参数,
  让PWR进入停止模式,要退出停止模式,则需要等待外部中断唤醒,
  所以当每次不计次时(即没有进入外部中断函数),芯片依旧处于停止模式
  当对射式红外传感器感应到计数时(此时进入外部中断函数),则唤醒芯片
  继续运行之前暂停的程序,以此反复.
*/


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

	while(1)
	{
		OLED_ShowNum(2, 1, CountSensor_Get(), 5);
		
		OLED_ShowString(3, 1, "Running");
		Delay_ms(100);
		OLED_ShowString(3, 1, "       ");
		Delay_ms(100);
		
		/*
		PWR进入停止模式
		---1.指定停止模式下的调节器状态
		---2.指定是否使用WFI或WFE指令进入停止模式。
		*/
		PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
		/*
		当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟(8MHz),
		所以需要重新将RCC时钟配置重置为默认重置状态(即HSE*9 = 72MHz)
		*/
		SystemInit(); 
	}
}

关键代码:

	//开启PWR的外设时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
		/*
		PWR进入停止模式
		---1.指定停止模式下的调节器状态
		---2.指定是否使用WFI或WFE指令进入停止模式。
		*/
		PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
		/*
		当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟(8MHz),
		所以需要重新将RCC时钟配置重置为默认重置状态(即HSE*9 = 72MHz)
		*/
		SystemInit(); 

 具体操作对应下图:

 待机模式:

代码:

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

/*
	待机模式(尽量把外部能关的一切耗电电路都关掉,减少耗电)
	---程序需要开启PWR的外设时钟以及设置指定的唤醒待机方式
	每次运行到PWR_EnterSTANDBYMode函数进入待机模式,
	PWR_EnterSTANDBYMode函数以下的代码程序就不会运行
	且每次唤醒后,程序会重头开始运行,因此在main程序中可以
	去掉while循环

*/
int main(void)
{
	OLED_Init();
	MyRTC_Init();
	
	//开启PWR的外设时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
	
	OLED_ShowString(1, 1, "CNT :");  //秒计数器值CNT
	OLED_ShowString(2, 1, "ALR :");  //闹钟值Alarm
	OLED_ShowString(3, 1, "ALRF:");  //闹钟标志位
	
	/*
	1.第一种唤醒方式---WKUP引脚的上升沿(WKUP引脚看芯片引脚图在哪个引脚)
	使能芯片的WAKEUP引脚,当WAKEUP引脚上升沿时刻时唤醒待机模式
	*/
	PWR_WakeUpPinCmd(ENABLE);
	
	/*
	2.第二种唤醒方式---RTC闹钟事件的上升沿
	设置闹钟为当前时间的10s后(当CNT的值与Alarm的值相同时,会置RTC_FLAG_ALR闹钟标志位为1)
	*/
	uint32_t Alarm = RTC_GetCounter() + 10;
	RTC_SetAlarm(Alarm);
	
	OLED_ShowNum(2, 6, Alarm, 10); //显示Alarm的值
	
	while(1)
	{
		//获取计数寄存器的值
		OLED_ShowNum(1, 6, RTC_GetCounter(), 10);   
		//获取闹钟标志位
		OLED_ShowNum(3, 6, RTC_GetFlagStatus(RTC_FLAG_ALR), 1);   
		
		//显示STANDBY,表示处于待机模式中
		OLED_ShowString(4, 9, "STANDBY");
		Delay_ms(1000);
		OLED_ShowString(4, 9, "       ");
		Delay_ms(100);
		
		OLED_Clear();//清OLED屏(模拟模块断电)
		
		PWR_EnterSTANDBYMode();//进入待机模式
	}
}

关键代码:

	//开启PWR的外设时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);

	/*
	1.第一种唤醒方式---WKUP引脚的上升沿(WKUP引脚看芯片引脚图在哪个引脚)
	使能芯片的WAKEUP引脚,当WAKEUP引脚上升沿时刻时唤醒待机模式
	*/
	PWR_WakeUpPinCmd(ENABLE);


	/*
	2.第二种唤醒方式---RTC闹钟事件的上升沿
	设置闹钟为当前时间的10s后(当CNT的值与Alarm的值相同时,会置RTC_FLAG_ALR闹钟标志位为1)
	*/
	uint32_t Alarm = RTC_GetCounter() + 10;
	RTC_SetAlarm(Alarm);


	PWR_EnterSTANDBYMode();//进入待机模式

  具体操作对应下图:

补充:修改主频

代码:

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

/*
	修改主频(Delay_ms默认是72MHz)
	在默认的主频72MHz下,"Running"字在OLED屏的闪烁周期为1s
	通过修改system_stm32f10x.c文件的可写属性,将主频设置为36MHz
	此时"Running"字在OLED屏的闪烁周期为2s,即频率延迟了1倍
*/

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

具体在system_stm32f10x.c文件下的此处修改主频: 

 

作者:罐头玩家

物联沃分享整理
物联沃-IOTWORD物联网 » STM32 PWR电源控制:睡眠、停止和待机模式详解

发表评论