STM32进入低功耗模式 备份SRAM和RTC模块都可以保持正常工作状态。


1 睡眠模式 sleep:
进入睡眠状态前采取以下措施:除保留将要唤醒Cortx内核的时钟之外,关闭所有外设时钟,并开启内部HSI(可设置为1MHz)
后,STM32睡眠消耗电流大概0.5mA左右。


2.停机模式 close down:
停机模式设置完成后,CPU遇到WFI或WFE指令就会停止工作,HSI和HSE进入关闭状态。但Flash和SRAM仍然保持电源供应,
此时STM32所有工作状态仍然保留着.和睡眠模式一样,停机模式也可以通过外设中断唤醒.
在停机模式下除了外部中断控制单元,所有设备的时钟都被禁止了,只能通过在GPIO引脚上产生电平边沿触发外部中断控制方式
将STM32从停机状态下唤醒. 外部中断通道除了与GPIO连接,还和RTC时钟报警事件连接,因此可以使用RTC模块实现定时将STM32
从停机状态中唤醒.
 STM32进入停机模式,其电流消耗降至24uA左右.在停机模式基础上,STM32还可以通过内部电压调整器调整内核工作电压可以达到
更低的功耗,通过设置STM32 PCR中的LPDS位可以使STM32内核也进入低功耗模式.这样整体电流可下降到14uA,如果开启RTC,需要
多消耗1.4uA电流.




STM32在使用HSI振荡器从停机模式恢复所需唤醒时间
恢复时间/us 恢复后的 备注
3.52 返回正常模式 从停机模式恢复到返回正常模式
5.42 返回正常模式+WFI指令 从停机模式恢复到正常模式,并执行WFI模式
5.32 返回低功耗模式+WFE指令 从停机模式恢复后返回低功耗模式,并执行WFE指令
7.21 返回低功耗模式+WFI指令 从停机模式恢复后返回低功耗模式,并执行WFI指令




3.待机模式 standby:
将Cortex_PCR中的SLEEP位置位,再将STM32_PCR的PDDS位置位后,STM32的待机模式就设置好了。待机模式下STM32处于完全


关闭状态:
内核电源、HSE、HSI都处于关闭状态。
和停机模式一样,可以通过RTC报警事件来将STM32从待机模式中唤醒,也可使用外部复位引脚,或通过独立看门狗产生的复位


信号将其唤醒,还可通过在GPIOA.0引脚产生一个上升沿来唤醒STM32,但前题是该引脚必须事先设置为唤醒(Wake Up Pin)引脚功能.
待机模式作为最低功耗模式,退出时间长达50us.进入待机模式,所有的SRAM数据,Cortex_M3处理器的寄存器和STM32的寄存器内容将
全部丢失. 即从待机模式唤醒后,相当于得到一个硬件复位的效果.


STM32待机模式下的电流消耗情况
STM32运行情况 VDD/VBAT3.3V VDD/VBAT-2.4V
HSI LSI 看门狗和RTC关闭 2uA N/A
LSI和RTC开启 1.4uA 1.08uA


按键调试的方法唤醒待机模式的系统
KEY WKUP PRINTF LED LCD
KEY:按键扫描


RTC闹钟中断唤醒待机模式的系统
用到RTCAlarm_IRQHandler() 和RTC_IRQHandler() 使用时 RTCAlarm_IRQHandler()函数的优先级一定要高于RTC_IRQHandler()
原因如下:
1,产生闹钟中断的前一瞬间,一定产生了秒中断,那么会先执行RTC_IRQHandler() 中断函数, 在RTC_IRQHandler() 执行的过程


中,闹钟中断标志又被挂起,


由于RTC_IRQHandler()是全局中断函数,必须清除所有的中断标志,程序才能退出该函数, 假如RTC_IRQHandler()  和


RTCAlarm_IRQHandler() 是同样的优先级,


要想让程序退出RTC_IRQHandler() 函数,那么你必须清除闹钟中断标志(如果不清除闹钟中断标志,程序会死在RTC_IRQHandler() 


), 这样问题又出现了,清除闹钟中断标志后,程序就不会进入RTCAlarm_IRQHandler(),那么RTCAlarm_IRQHandler()函数永远也


不会被执行。


只有这样做
设置闹钟中断函数RTCAlarm_IRQHandler() 的优先级高于全局中断函数RTC_IRQHandler(),
 在执行全局中断函数RTC_IRQHandler() 的时候,如果产生闹钟中断,那么中断嵌套去执行RTCAlarm_IRQHandler(),执行完毕


RTCAlarm_IRQHandler()后,再去执行RTC_IRQHandler() 。


对应程序: 

 static void RTC_NVIC_Config(void) 

 { 
  

   NVIC_InitTypeDef NVIC_InitStructure; 

NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; 
 //RTC全局中断 

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
 //先占优先级2位,从优先级2位 

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; 
 //先占优先级3位,从优先级4位 

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
 //使能该通道中断 

NVIC_Init(&NVIC_InitStructure); 
 //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 

 

NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;  //闹钟中断 

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //比RTC全局中断的优先级高 

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

NVIC_Init(&NVIC_InitStructure); 

 

 } 



 //RTC时钟中断 

 //每秒触发一次   

 //extern u16 tcnt;  

 void RTC_IRQHandler(void) 

 { 
   

if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断 

{ 
  

RTC_Get();//更新时间    

   
 } 

  
   

RTC_ClearITPendingBit(RTC_IT_SEC); 
 //清秒中断 

//RTC_WaitForLastTask(); 
   
     
  
  
  

 } 





 static void RTC_Alarm_EXIT(void) 

{  

EXTI_InitTypeDef EXTI_InitStructure; 

EXTI_ClearITPendingBit(EXTI_Line17); 

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 

     EXTI_InitStructure.EXTI_Line = EXTI_Line17; 

     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 

EXTI_InitStructure.EXTI_LineCmd = ENABLE; 

     EXTI_Init(&EXTI_InitStructure); 



} 



void RTCAlarm_IRQHandler(void) 

{      

if(RTC_GetITStatus(RTC_IT_ALR) != RESET) 

       { 



       } 

EXTI_ClearITPendingBit(EXTI_Line17); 

//RTC_WaitForLastTask(); 

RTC_ClearITPendingBit(RTC_IT_ALR); 

//RTC_WaitForLastTask(); 

  }