一、STM32低功耗待机模式+ WKUP引脚的上升沿来唤醒
STM32的低功耗模式:
1.睡眠模式(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)
2.停止模式(所有的时钟都已停止)
3.待机模式(1.8V电源关闭)(功耗最低的模式)

那我们要怎么来进入待机模式?又要怎么唤醒呢?
看到“进入”中的红色数字标号了吧?没错了,我们只要按照此步骤来设置相应的寄存器就行了。


要怎么来唤醒呢?通过外部中断触发来唤醒:
void Wkup_Init(void){EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;KEY_Init();//我的IO初始化在按键里已经初始化了RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);EXTI_InitStructure.EXTI_Line = EXTI_Line0; //PA0EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;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 = 0x02;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);if(Check_up() == 0)//初始化后,没有按下按键,系统直接进入了待机模式,需要人为的唤醒{Sys_Standby(); //进入待机模式}}
//正常模式下会运行中断服务函数,而待机模式下则不会运行中断服务函数,因为待机模式下MCU不工作,所以上升沿的作用也仅仅是唤醒。
//在这里提醒:唤醒只需要上升沿,所以从待机模式切换到正常模式下从始至终都不会执行中断服务函数
void EXTI0_IRQHandler(void){EXTI_ClearITPendingBit(EXTI_Line0);if(Check_up()){Sys_Enter_Standby();}}
步骤:
1.使能PWR时钟:RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
2.使能唤醒的功能:PWR_WakeUpPinCmd(ENABLE);
3.进入待机模式 :PWR_EnterSTANDBYMode();
代码:
void Sys_Standby(void) //在唤醒初始化中调用{RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);PWR_WakeUpPinCmd(ENABLE);PWR_EnterSTANDBYMode();}void Sys_Enter_Standby(void)//在中断函数里调用,用来复位,然后进入待机模式{RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //只是复位了IO口,0x01fc见RCC_APB2RSTRSys_Standby();}
最后我们给出按键检测的处理程序,在这里,3S只是一个效果,也可以不用。
u8 Check_up(void){u8 t = 0;u8 tx = 0;LED0 = 0;while(1){if(KEY3 == 1) //检测到按键按下{t++;tx = 0;}else{tx++;if(tx > 3){LED0 = 1;return 0; //错误按键或者按键时间不够}}delay_ms(30);if(t > 100) //100*30ms = 3s{LED0 = 0;return 1;// 3s}}}
/*从正常运行模式切换到待机模式:按住wkup键,外部中断0中断被触发,执行中断服务函数Check_up()函数开始检测 如果时间没超过3s,返回零 。这时工作在正常运行模式,如果按住时间超过了3s,返回值为1,进入待机模式。我们的程序在刚开始运行时就是没有按键按下,所以没有上升沿,初始化函数里条件成立,从而进入了待机模式:请看初始化的代码:*/
if (Check_up() == 0)
{
Sys_Standby(); //进入待机模式
}
/*从待机模式切换到正常运行模式 按住wkup键的那一瞬间会有一个上升沿,而这个上升沿执行了唤醒功能但是没有执行外部中断0的中断服务函数。待机模式下cpu是不工作的 从待机模式唤醒后的代码执行等同于复位后的执行,所以程序又会从头开始执行(这句话很重要) 然后又会执行到 Check_up()函数检测 如果按住键盘的时间没有超过3s 还是会处于待机模式 加入超过了3s,返回值为1,条件不成立 就会切换到正常运行模式 所以结论就是外部中断0的中断服务程序在待机模式切换到正常运行模式的时候从始至终是不会运行的。记住:唤醒中只是说需要上升沿,并没有说要进入中断*/
所以:1.如果是正常运行,先执行中断程序,判断是否3秒,决定是否待机。2.如果是待机状态,则先复位并初始化,判断是否3秒,决定是否开机。
二、STM32进入待机模式,使用闹钟和WKUP唤醒
STM32进入待机模式和怎么唤醒待机模式的方法:

整个过程可以分为3步:
第一:设置RTC闹钟(用于时间到了闹钟时间,唤醒单片机)
第二:进入待机模式(调用PWR的一个函数就进入了待机模式)
第三:使用闹钟信号,唤醒待机模式 (闹钟到了就唤醒单片机,不需要其他设置,设置了闹钟就可以了)可以开启WKUP(也是PWR的一个函数,这样PA0有上升信号也能唤醒单片机)

主要就是上面提到的三步,其他的程序还要自己来编写,需要闹钟或是WKUP功能时,选择性添加对应的代码就可以了。
上面的程序编译后下载到单片机中,看到的现象就是马上进入了待机模式,因为有OLED清屏的代码,所以直接看到OLED清屏了,每隔10秒钟屏幕亮一次,或者是PA0有了上升沿(PA0接高电平的时候屏幕会亮起):
