STM32F407待机唤醒

疑问

在做待机唤醒实验时,会有这样的疑问:只有进入待机模式的代码,那么唤醒是如何唤醒的?

原理

(此节主要针对待机唤醒原理进行简单介绍,可以根据自己情况自动略过)

STM32F4待机模式

  • 在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。
  • STM32F4 的 3 种低功耗模式
  • 在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需要 2.2uA 左右的 电流。停机模式是次低功耗的,其典型的电流消耗在350uA 左右。最后就是睡眠模式了。

进入/退出待机模式

在这里插入图片描述拓展:

  • 在进入模式的第三步:将WUF位清零,查看寄存器PWR_CSR。
    在这里插入图片描述清零需要通过PWR_CR进行配置:CWUF位置1。
    在这里插入图片描述
  • 退出模式
  • 根据图1及下面stm32部分时钟树可知,在待机的状态下,PLL、HSI 和 HSE 振荡器被断电、1.2V供电区别断电,可以认为只有LSI、LSE振荡器在工作,因此RTC、独立看门狗可以工作,从而进行待机唤醒。(还有WKUP上升沿、NRST复位)
    在这里插入图片描述

代码

#include "wkup.h"
#include "led.h"
#include "delay.h"	
#include "usart.h"																	   
 
//系统进入待机模式
void Sys_Enter_Standby(void)
{		
  while(WKUP_KD);			//等待WK_UP按键松开(在有RTC中断时,必须等WK_UP松开再进入待机)
 
	RCC_AHB1PeriphResetCmd(0X04FF,ENABLE);//复位所有IO口
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR时钟		 
	 
	PWR_BackupAccessCmd(ENABLE);//后备区域访问使能

	//这里我们就直接关闭相关RTC中断
	RTC_ITConfig(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA,DISABLE);//关闭RTC相关中断,可能在RTC实验打开了。
	RTC_ClearITPendingBit(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA);//清楚RTC相关中断标志位。
	
	PWR_ClearFlag(PWR_FLAG_WU);//清除Wake-up 标志
	
	PWR_WakeUpPinCmd(ENABLE);//设置WKUP用于唤醒
	
	PWR_EnterSTANDBYMode();	//进入待机模式
	 
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
//      0:错误的触发	
u8 Check_WKUP(void) 
{
	u8 t=0;
	u8 tx=0;//记录松开的次数
	LED0=0; //亮灯DS0 
	while(1)
	{
		if(WKUP_KD)//已经按下了
		{
			t++;
			tx=0;
		}else 
		{
			tx++; 
			if(tx>3)//超过90ms内没有WKUP信号
			{
				LED0=1;
				return 0;//错误的按键,按下次数不够
			}
		}
		delay_ms(30);
		if(t>=100)//按下超过3秒钟
		{
			LED0=0;	  //点亮DS0 
			return 1; //按下3s以上了
		}
	}
}  
//中断,检测到PA0脚的一个上升沿.	  
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{ 		    		    				     		    
  EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
	if(Check_WKUP())//关机?  
	{		  
		Sys_Enter_Standby(); //进入待机模式 
	}
} 

//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{	  
  GPIO_InitTypeDef  GPIO_InitStructure;
	NVIC_InitTypeDef   NVIC_InitStructure;
	EXTI_InitTypeDef   EXTI_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化	

	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PA0 连接到中断线0
	
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;//LINE0
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
  EXTI_Init(&EXTI_InitStructure);//配置

	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);//配置NVIC
	
	//(检查是否是正常开)机    		 
  if(Check_WKUP()==0)
	{
		Sys_Enter_Standby();	//不是开机,进入待机模式  
	}
}

此处为wkup.c代码,比较简单,这里不再进行阐述,下面主要针对上述疑问进行解释。(通过查阅资料,自行理解的逻辑)

理解

  1. 首先,开机后,从int main()函数进行初始化,进行到WKUP_Init();对PA0进行相关配置,检查是否长按开机键,没有,进入Sys_Enter_Standby()函数,在函数内最后进入待机模式:PWR_EnterSTANDBYMode()。

  2. PWR_EnterSTANDBYMode()配置在原理中已经进行介绍,不再重复,主要针对函数内的WFI进行介绍:
    WFI: wait for Interrupt 等待中断,即下一次中断发生前都在此hold住不干活
    也就是说:当前大环境是正常运行状态,当运行于此处时,卡住不进行后续代码执行,相当于进行待机处理。
    所以在初始化时,运行到WFI就卡在了一个地方

  3. 当按键wkup被按下时,其实已经进行了待机唤醒处理,(从按下时,灯光亮了一下就可以看出来,程序已经开始运行了,没有继续卡在原处),此时是从int main()函数第一行开始重新运行。进行到WKUP_Init();对PA0进行相关配置,检查是否长按开机键。

  4. 没有按够3s,重复上述1、2步骤;

  5. 当按键达到3s后,跳过WKUP_Init()函数中的ifCheck_WKUP()函数,程序正常运行,从而达到唤醒功能。并配置PA0中断方式。

  6. 当再次按键达到3s后,进入中断,判断有没有按够3s。时间不够,继续运行正常状态;时间达到3s,Sys_Enter_Standby()
    再次进入待机模式。

void EXTI0_IRQHandler(void)
{ 		    		    				     		    
 EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
   if(Check_WKUP())//关机?  
   {		  
   	Sys_Enter_Standby(); //进入待机模式 
   }
} 
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值