STM32工作笔记0066---待机唤醒实验-设备低功耗-M3H

 技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

因为工作需要这里,跳过了LCD的实验,后面会补上

.

待机模式的功耗最低.

进入3种低功耗模式的方法

这里着重说待机模式:

这里这个WKUP引脚,就是PA0这个IO口.

进入到待机模式主要使用到了两个寄存器一个是:

PWR_CR寄存器,这里设置PDDS为可以进入深度睡眠进入待机模式

配置这个位,可以参考文档.

还需要再配置一个:

PWR_CSR寄存器,的这个WUF这个位.

然后还有,SLEEPDEEP这个位.这个位实际上是在SYSTEM CONTROL B..这个寄存器中来配置的

等一会在代码中看是如何配置的

总结一下就是要配置上面看到的标红的这几个位,才能进入待机模式.

然后再看看退出.

这里咱们一般用WKUP引脚的上升沿,来控制唤醒,或者是RTC闹钟事件的上升沿来配置唤醒,

这两个经常用,其他的不怎么用.

然后打开待机唤醒实验来看看:

然后来看一下,待机唤醒的函数.

看到这里有个:

这个待机唤醒的函数

void PWR_WakeUpPinCmd(FunctionalState NewState);

这个就是使能WKUP这个引脚,也就是待机唤醒的引脚.

void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);//进入停止模式的函数
void PWR_EnterSTANDBYMode(void);//进入待机模式的函数.

先看一下这个进入待机模式的函数

下面是进入待机模式的三步走:

从下到上.

可以看到这个函数

/**
  * @brief  Enters STANDBY mode.
  * @param  None
  * @retval None
  */
void PWR_EnterSTANDBYMode(void)
{
  /* Clear Wake-up flag */
  PWR->CR |= PWR_CR_CWUF; //1.先设置WUF
  /* Select STANDBY mode */
  PWR->CR |= PWR_CR_PDDS;//2.再设置PDDS
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR |= SCB_SCR_SLEEPDEEP;//3.再设置SLEEPDEEP
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM   )
  __force_stores();
#endif
  /* Request Wait For Interrupt */
  __WFI();
}

然后再看看那个进入这个停止模式

可以看到,这里进入停机模式,实际上是多了一个

LPDS

/**
  * @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)
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_PWR_REGULATOR(PWR_Regulator));
  assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
  
  /* Select the regulator state in STOP mode ---------------------------------*/
  tmpreg = PWR->CR;
  /* Clear PDDS and LPDS bits */ //1.可以看到进入停止模式,这里多了一个LPDS的设置.
  tmpreg &= CR_DS_MASK;
  /* Set LPDS bit according to PWR_Regulator value */
  tmpreg |= PWR_Regulator;
  /* Store the new value */
  PWR->CR = tmpreg;
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR |= SCB_SCR_SLEEPDEEP;
  
  /* Select STOP mode entry --------------------------------------------------*/
  if(PWR_STOPEntry == PWR_STOPEntry_WFI)
  {   
    /* Request Wait For Interrupt */
    __WFI();
  }
  else
  {
    /* Request Wait For Event */
    __WFE();
  }
  
  /* Reset SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);  
}

然后再看看待机唤醒的步骤

然后再看看待机唤醒实验

这里我们把LCD的实验拿出来,来写一个手把手的,待机唤醒的实验

这里首先把STM32F10X_PWR.C这个文件添加进来.

然后把mian.c中的循环都删除掉,只留下对应的初始化函数.

这里我们要做的实验是这样,我们要,按下KEY0然后,进入待机模式,然后

按下WKUP按键,使能EWUP位,以后等待上升沿到来,唤醒系统.

可以看到首先,要去

初始化KEY_INIT()

然后写个循环,然后在循环中可以扫描KEY0按下的话就

去做对应的进入睡眠的动作:

按照下面的这三个步骤来做.

然后这类使能电源时钟,代码再rcc中.

用下面这个函数来使能电源时钟.

可以看看这个代码:

很简单:

可以看到首先,使能电源时钟,

然后执行PWR_WakeUpPinCmd()使能WKUP引脚,等待上升沿唤醒

然后进入待机模式

PWR_EnterSTANDBYMode()

然后,接下来为了测试,咱们把LCD显示的一部分字,加进来,系统启动的时候

先去显示一些文字.

然后再去下载到开发版,看效果.

代码下载之前:

代码下载以后:

可以看到显示了咱们LCD要显示的文字.

然后按下KEY0可以看到,系统进入待机模式了

然后,再按下WKUP按键以后,可以看到系统就变亮了0,唤醒了.

然后咱们再来看一下,待机唤醒的实验.

首先看一下,系统启动以后首先执行

WKUP_INIT()这个函数.

先去初始化

初始化的话,这里可以看到,先去使能GPIOA口的时钟,还有AFIO时钟,因为用到了

优先级中断,所以这里要使能AFIO这个时钟.

然后设置了PA0引脚的模式,这里上拉输入什么的

然后设置对应的中断.

然后设置中断优先级.

然后还有一个调用这里的Check_WKUP()这个函数,调用这个函数的时候会

这个函数会去检测是不是到了3秒了,按下3秒以上了返回1,否则返回0

 int main(void)
 {	 
  
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
 	LED_Init();			     //LED端口初始化	 	
	WKUP_Init(); //待机唤醒初始化
	LCD_Init();	 //LCD初始化
	POINT_COLOR=RED;
	 
	LCD_ShowString(30,50,200,16,16,"Elite STM32");	
	LCD_ShowString(30,70,200,16,16,"WKUP TEST");	
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2015/1/14");
	 
	while(1)
	{
		LED0=!LED0;
		delay_ms(250);
	}
 }
//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{	
  GPIO_InitTypeDef  GPIO_InitStructure;  		  
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOA和复用功能时钟

	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;	 //PA.0
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//初始化IO
    //使用外部中断方式
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);	//中断线0连接GPIOA.0

  EXTI_InitStructure.EXTI_Line = EXTI_Line0;	//设置按键所有的外部线路
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			//设外外部中断模式:EXTI线路为中断请求
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  //上升沿触发
 	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);	// 初始化外部中断

	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键所在的外部中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级2级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	if(Check_WKUP()==0) Sys_Standby();    //不是开机,进入待机模式  
	
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
//      0:错误的触发	
u8 Check_WKUP(void) 
{
	u8 t=0;	//记录按下的时间
	LED0=0; //亮灯DS0 
	while(1)
	{
		if(WKUP_KD)
		{
			t++;			//已经按下了 
			delay_ms(30);
			if(t>=100)		//按下超过3秒钟
			{
				LED0=0;	 	//点亮DS0 
				return 1; 	//按下3s以上了
			}
		}else 
		{ 
			LED0=1;
			return 0; //按下不足3秒
		}
	}
} 
//中断,检测到PA0脚的一个上升沿.	  
//中断线0线上的中断检测

可以看到这里30毫秒就去检测一次,检测到100次的时候,也就是超过3秒了就返回1.

然后下面是进入待机模式的,和前面咱们写的代码是一样的

这个时候,画面启动的时候是这样,也就说,

系统启动的时候,会检测有没有按下wkup按键,按下了多久,显然刚启动的时候,咱们没有按下

wkup按键,这个时候,check_wkup就会返回0,返回0的时候,那么系统就会自动进入

待机模式.黑屏的,然后当咱们按下wkup按键的时候,系统会再去从main函数开始执行,这个时候

再去执行check_up函数的时候,这个时候检测到wkup按键被按下了3秒,那么就返回1,也就是不会

进入待机模式,不会进入待机模式,那么就会接着执行下面的函数,也就是LCD显示的内容,那么系统就亮了.

注意这里的屏幕亮了是因为程序从新从main函数开始执行导致的.

可以看到这个WKUP_INIT()这个函数,下面还是有LCD显示的函数的,只要是返回了1,那么,系统没有进入待机模式,那么

代码就会往下执行.就会执行LCD显示文字的代码.LCD屏幕就亮了.

下载到开发版看看效果,可以看到

首先下载到开发版以后,屏幕是暗的:

连续按下3秒以后可以看到,程序会亮了

然后这个时候如果我们再按下3秒,就会又进入待机模式了

这个是怎没做的呢?

因为咱们前面设置了中断.

PA0的中断,那么在系统的LCD屏亮着的情况下,也就是没有进入待机模式的情况下,

中断是起作用的,而在待机模式下,中断是不起作用的,那么在正常运行的情况,下如果我们按下了,3秒,那么

会检测到上升沿,就会触发PA0的中断,那么就会进入中断函数,可以看到中断函数中判断了如果按下的时间超过3秒

返回1,也就是,系统会又进入待机模式了.

那么再按下wkup按键的,时候因为待机模式下,代码会从main函数从头开始执行,这里代码执行到

WKUP_INIT()的时候,如果没有按下超过3秒,就自动进入待机模式,如果超过3秒了,屏幕又会亮了,

这样就显示了按3秒,关机,再按3秒启动的效果.

猜你喜欢

转载自blog.csdn.net/lidew521/article/details/108273155