STM32_3种低功耗模式

STM32的3种低功耗模式
①睡眠模式:内核停止,外设比如NVIC,系统时钟Systick仍然运行
②停止模式:所有时钟停止,1.8V内核电源工作
③待机模式:1.8V内核电源关闭;只有备份寄存器和待机电路维持供电,寄存器和SRAM内容丢失,功耗最低
运行模式下降低功耗:降低系统时钟,关闭APB,AHB总线上的未使用外设时钟

STM32待机模式
STM32_3种低功耗模式_第1张图片

进入待机模式前,对于使用了RTC闹钟中或者RTC周期性唤醒中断的时候,需要处理

  • a) 禁止 RTC 闹钟中断(RTC_CR 寄存器中的 ALRAIE 或 ALRBIE 位)
  • b) 将 RTC 闹钟 (ALRAF/ALRBF) 标志清零
  • c) 将 PWR 唤醒 (WUF) 标志清零
  • d) 使能 RTC 闹钟中断
  • e) 重新进入低功耗模式

待机唤醒配置步骤:
①使能电源时钟:RCC_APB1PeriphClockCmd();
②RTC相关处理:关闭RTC相关中断
③设置WK_UP引脚作为唤醒源
设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒
PWR_WakeUpPinCmd();
④设置SLEEPDEEP位,设置PDDS位,执行WFI指令,进入待机模式
PWR_EnterSTANDBYMode();

//系统进入待机模式
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相关处理进行清零:1)禁止 RTC 闹钟中断(RTC_CR 寄存器中的 ALRAIE 或 ALRBIE 位)
						  2)将 RTC 闹钟 (ALRAF/ALRBF) 标志清零
						  3)将 PWR 唤醒 (WUF) 标志清零                                  */	
	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相关标志位,比如RTC入侵,RTC唤醒	
	PWR_ClearFlag(PWR_FLAG_WU);                    //清除Wake-up 标志,这个标志好像在唤醒后会置为1
	
			
	//设置WK_UP引脚作为唤醒源,设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒
	PWR_WakeUpPinCmd(ENABLE);    //使能唤醒管脚功能,设置 PWR_CSR 的 EWUP 位,使能 WK_UP 用于将 CPU 从待机模式唤醒
		
	
	//设置SLEEPDEEP位,设置PDDS位,执行WGI指令,进入待机模式	
	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 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);           	 //初始化	

	//(检查是否是正常开机 )   		 
	if(Check_WKUP()==0)
	{
     
		Sys_Enter_Standby();	//不是正常唤醒,进入待机模式  
	}
	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

}


//中断,检测到PA0脚的一个上升沿.	  
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{
      		    		    				     		    
    EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
	if(Check_WKUP())   //关机?
	{
     		  
		Sys_Enter_Standby(); //进入待机模式 
	}
} 

你可能感兴趣的:(初始者,stm32)