如果使用 WFI 指令进入睡眠模式,则嵌套向量中断控制器 (NVIC) 确认的任意外设中断都会
将器件从睡眠模式唤醒。
如果使用 WFE 指令进入睡眠模式,MCU 将在有事件发生时立即退出睡眠模式。唤醒事件可
通过以下方式产生:使能外设中断,但是不用NVIC。在内核系统控制寄存器SEVONPEND=1;SLEEPONEXIT = 0;配置外部中断为事件模式;
wfi进入休眠:任意中断退出休眠;
WFE进入休眠如下10.2.3
10.2.3 唤醒事件管理
STM32F4xx 能够处理外部或内部事件来唤醒内核 (WFE)。唤醒事件可通过以下方式产生:
● 在外设的控制寄存器使能一个中断,但不在 NVIC 中使能,同时使能 Cortex™-M4F 系统
控制寄存器中的 SEVONPEND 位。当 MCU 从 WFE 恢复时,需要清除相应外设的中
断挂起位和外设 NVIC 中断通道挂起位(在 NVIC 中断清除挂起寄存器中)。
● 配置一个外部或内部 EXTI 线为事件模式。当 CPU 从 WFE 恢复时,因为对应事件线的
挂起位没有被置位,不必清除相应外设的中断挂起位或 NVIC 中断通道挂起位。
在m4内核的SCB系统控制块中
需要的在2和3位
- #include"wkup.h"
-
-
-
-
-
- #define WKUP_KD PAin(0) //PA0 检测是否外部WK_UP按键按下
-
- void wkup_init()
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- EXTI_InitTypeDef EXTI_InitStruct;
- NVIC_InitTypeDef NVIC_InitStruct;
- RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_SYSCFG , ENABLE);//外部中断需要sysCFG时钟
-
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
- GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;//外部中断只能输入模式,没有复用模式;
- GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
- GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_DOWN;
- GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;
- GPIO_Init(GPIOA, & GPIO_InitStruct);
-
- SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//库文件sysfg文件的函数,配置A0为外部中断
-
- EXTI_InitStruct.EXTI_Line=EXTI_Line0 ;//外部中断
- EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
- EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;
- EXTI_InitStruct.EXTI_LineCmd= ENABLE;
- EXTI_Init( & EXTI_InitStruct);
-
- NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=3;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority=3;
- NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
- NVIC_Init(&NVIC_InitStruct);
-
-
-
- }
-
-
- void EXTI0_IRQHandler()
- {
- EXTI_ClearITPendingBit( EXTI_Line0 );
- printf("\r\n 激活88888888888 \r\n");
- }
- void sys_enter_sleep()
- {
- __WFI();
- SCB->SCR&=~(3<<1);//SLEEPDEEP SLEEPONEXIT 都等于0
-
- }
-
main
- #include "main.h"
- #define tmep_len 30
- uint8_t temp_buf[tmep_len]={0};
-
- void test();
- uint8_t *mian_temp;
- double time_us;
- int main(void)
- {
- time_struct times;
- u8 key,flag ,i,n=5; //保存键值
- long long temp_32=0;
- static bool cnt;
- // delay_init(168); //初始化延时函数
- LED_Init(); //初始化LED端口
- BEEP_Init(); //初始化蜂鸣器端口
- //KEY_Init(); //初始化与按键连接的硬件接口
- LED1=!LED1;
- LED0=!LED0;
- wkup_init();//配置中断唤醒
- while(1)
- {
-
-
-
- for(i=0;i<20;i++)
- { temp_32=168*1000*100;
- while(temp_32--);
- LED1=!LED1;
- LED0=!LED0;
- if(i==5)
- {
- sys_enter_standby();
- }
- }
-
-
- }
-
- }
库函数已经包装好
-
-
- void sys_enter_stop()
- {
-
- PWR_EnterSTOPMode(PWR_MainRegulator_ON, PWR_STOPEntry_WFI);//库函数
-
-
- }
PWR_EnterSTANDBYMode(void)此库函数中已经存在PDDS和SLEPDEEP位设置;和WFI;
1、独立的看门狗 (IWDG):
2、实时时钟 (RTC):
3、内部 RC 振荡器 (LSI RC):
4、外部 32.768 kHz 振荡器 (LSE OSC):
检测到外部复位(NRST 引脚)、IWDG 复位、WKUP 引脚上升沿、RTC 闹钟、入侵事件
或时间戳时间时,微控制器退出待机模式
唤醒时间,就是复位时间;应该不是复位,而是时间长;
- #include"wkup.h"
-
-
-
-
-
- #define WKUP_KD PAin(0) //PA0 检测是否外部WK_UP按键按下
-
- void wkup_init()
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- EXTI_InitTypeDef EXTI_InitStruct;
- NVIC_InitTypeDef NVIC_InitStruct;
- RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_SYSCFG , ENABLE);//外部中断需要sysCFG时钟
-
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
- GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;//外部中断只能输入模式,没有复用模式;
- GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
- GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_DOWN;
- GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;
- GPIO_Init(GPIOA, & GPIO_InitStruct);
-
- SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//库文件sysfg文件的函数,配置A0为外部中断
-
- EXTI_InitStruct.EXTI_Line=EXTI_Line0 ;//外部中断
- EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
- EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;
- EXTI_InitStruct.EXTI_LineCmd= ENABLE;
- EXTI_Init( & EXTI_InitStruct);
-
- NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=3;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority=3;
- NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
- NVIC_Init(&NVIC_InitStruct);
-
-
-
- }
-
-
- void EXTI0_IRQHandler()
- {
- EXTI_ClearITPendingBit( EXTI_Line0 );
- printf("\r\n 激活88888888888 \r\n");
- }
-
- void sys_enter_standby()
- {
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==0)
- {
- // RCC_AHB1PeriphResetCmd(0X04FF,ENABLE);//复位所有IO口
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启电源控制管理时钟,才能操作低功耗
-
- PWR_BackupAccessCmd(ENABLE);//备份RTC和SRAM
-
- RTC_ClearITPendingBit(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA|RTC_IT_TAMP1|RTC_IT_TAMP2);//禁止RTC中断和清除全部标记
- RTC_ITConfig(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA|RTC_IT_TAMP, DISABLE);
-
-
- PWR_ClearFlag(PWR_FLAG_WU);//清除wakup 的唤醒标志
- PWR_WakeUpPinCmd(ENABLE); //使能wake up脚唤醒
- PWR_EnterSTANDBYMode(); //进入到待机模式
-
-
- }
-
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
main
-
- #include "main.h"
- #define tmep_len 30
- uint8_t temp_buf[tmep_len]={0};
-
- void test();
- uint8_t *mian_temp;
- double time_us;
- int main(void)
- {
- time_struct times;
- u8 key,flag ,i,n=5; //保存键值
- uint32_t temp_32=0;
- static bool cnt;
- // delay_init(168); //初始化延时函数
- software_times_base_init( 168 );
- uart_init(115200);
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- LED_Init(); //初始化LED端口
- BEEP_Init(); //初始化蜂鸣器端口
- KEY_Init(); //初始化与按键连接的硬件接口
- LED1=!LED1;
- LED0=!LED0;
- wkup_init();
- while(1)
- {
- TimesMs( × );
- if(times.Delay>3000)
- {
- times.Delay=0;
- printf("\r\n 2222222222222222222 \r\n");
- }
- key=KEY_Scan(1);
- if(key==1)
- {
- sys_enter_standby();
- LED1=!LED1;
- LED0=!LED0;
- }
-
- }
-
- }
-
-
程序效果:进入待机后不再打印东西;中断唤醒,打印一个已经唤醒标志,并且恢复之前未完成的步骤;