STM32低功耗停止模式 以及简述判断中断的两种方式

#include "wkup.h"
#include "led.h"
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//待机唤醒 代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/7
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
//////////////////////////////////////////////////////////////////////////////////

#if 0
void PWR_EnterSleepMode(uint8_t PWR_SLEEPEntry); //睡眠模式
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);  //停机模式
void PWR_EnterSTANDBYMode(void);    //待机模式
#define PWR_Regulator_ON               //电源不进低功耗 唤醒基本没延迟
#define PWR_Regulator_LowPower         //电源进去低功耗 不过唤醒启动有一点延迟    

#define PWR_STOPEntry_WFI              //中断唤醒
#define PWR_STOPEntry_WFE              //事件唤醒

#endif

int exitflag;
void Sys_Standby(void)
{  
//	NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);	//使能PWR外设时钟
	PWR_WakeUpPinCmd(ENABLE);  //使能唤醒管脚功能
	//PWR_EnterSTANDBYMode();	  //进入待命(STANDBY)模式   待机模式	
	//                                     任意中断             事件
	//PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI|PWR_STOPEntry_WFE);//停机模式模式 
	PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);

}
//系统进入待机模式
void Sys_Enter_Standby(void)
{			 
	//RCC_APB2PeriphResetCmd(0X01FC,DISABLE);	//复位所有IO口
	Sys_Standby();
	//SystemInit();//重要,由于停机下对所有时钟关闭,所以唤醒需要重新配置时钟!
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
//      0:错误的触发	
u8 Check_WKUP(void) 
{
	u8 t=0;	//记录按下的时间
	LED0=0; //亮灯DS0 
	while(1)
	{
		if(WKUP_KD)
		{
			t++;			//已经按下了 
			delay_ms(30);//N190729164522608323
			if(t>=100)		//按下超过3秒钟
			{
				LED0=0;	 	//点亮DS0 
				return 1; 	//按下3s以上了
			}
		}else 
		{ 
			LED0=1;
			return 0; //按下不足3秒
		}
	}
} 
//中断,检测到PA0脚的一个上升沿.	  
//中断线0线上的中断检测


//PA0 WKUP唤醒初始化
void STOP_Init(void)
{	
  GPIO_InitTypeDef  GPIO_InitStructure;  		  	
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOA
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//另外, STM32 的所有 GPIO 都引入到 EXTI 外部中断线上,使得所有的 GPIO 都能作为外部中断的输入
//源。所以如果把 GPIO 用作 EXTI 外部中断时,还需要开启 AFIO 时钟。




	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1;	 //PA.0 PA.1
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;//上拉输入
	GPIO_Init(GPIOC, &GPIO_InitStructure);	//初始化IO
	

    //使用外部中断方式
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, 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);	// 初始化外部中断
	    //使用外部中断方式
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);	//中断线0连接GPIOA.1
	EXTI_InitStructure.EXTI_Line = EXTI_Line1;	//设置按键所有的外部线路
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			//设外外部中断模式:EXTI线路为中断请求
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising ;  //    下降沿触发EXTI_Trigger_Falling 上升沿触发EXTI_Trigger_Rising
 	EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能外部中断通道
	EXTI_Init(&EXTI_InitStructure);	// 初始化外部中断

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


void EXTI0_IRQHandler(void)
{ 		    		    				     		    
	if(EXTI_GetITStatus(EXTI_Line0)!=RESET)    //按压检测口中断信号出现 判断中断是否发生
		{ 	

	 exitflag++;	
Sys_Standby();	//执行中断事件?
//LED0=0;		
//SystemInit();		
			EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
			EXTI_ClearFlag(EXTI_Line0); // 清除LINE10上的中断标志位			
			}
} 
// EXTI_ClearFlag// 清除LINE10上的中断标志位
//EXTI_GetFlagStatus  If(EXTI_GetFlagStatus(EXTI_Line3)!-=RESET)//判断是否置位
//EXTI_GetITStatus()会先判断该中断是否使能,若使能了再判断中断标志位,
//而EXTI_GetFlagStatus()直接判断中断标志位是否置位。
//所以说方式的EXTI_GetITStatus()会好点,一般配合EXTI_ClearITPendingBit()使用




 void NVIC_CoreReset(void)
{
  __DSB();                                                          /* Ensure all outstanding memory accesses included
                                                                       buffered write are completed before reset */
  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
                           (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
                            SCB_AIRCR_VECTRESET_Msk    );         /* Keep priority group unchanged */
  __DSB();                                                          /* Ensure completion of memory access */
 
  for(;;)                                                           /* wait until reset */
  {
    __NOP();
  }
}
void EXTI1_IRQHandler(void)
{ 		  
	if(EXTI_GetITStatus(EXTI_Line1)!=RESET)    //按压检测口中断信号出现
		{           
				SystemInit();
		__set_FAULTMASK(1); //关闭所有中断
				NVIC_SystemReset(); //复位	
				NVIC_CoreReset();
			RTC_WaitForLastTask();

			LED0=1;
			PWR_WakeUpPinCmd(ENABLE);  //使能唤醒管脚功能
			
			EXTI_ClearITPendingBit(EXTI_Line1); // 清除LINE11上的中断标志位
			EXTI_ClearITPendingBit(EXTI_Line1); // 清除LINE11上的中断标志位
			EXTI_ClearFlag(EXTI_Line1); // 清除LINE11上的中断标志位
		}

} 














发布了112 篇原创文章 · 获赞 120 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/qq_36958104/article/details/98031075