STM32基于固件库学习笔记(5)电源管理之低功耗模式(睡眠、停止、待机)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43993734/article/details/101423336

低功耗模式

功耗的高低,决定了系统工作的时间,在需要长久间隔时间检测数据,又不可能人实时去操作的项目,最先考虑的就是功耗问题了, 功耗越低产品使用时间就更久。也就是说当CPU不需继续运行时,就可以利用多种低功耗模式来节省功耗,例如等待某个外部事件时。 用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。

STM32F10xx有三种低功耗模式:

1. 睡眠模式:(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)
2. 停止模式: 所有的时钟都停止。
3. 待机模式: 1.8V电源关闭,是最低功耗模式
  当处于运行模式,还可以使用降低系统时钟、关闭APB和AHB总线上没有使用的外设时钟两种方式降低功耗。

(一)睡眠模式

1. 进入睡眠模式
电源控制(PWR)

  1. SLEEP-NOW:如果SLEEPONEXIT位被清除,当WRI或WFE被执行时,微控制器立即进。
  2. SLEEP-ON-EXIT:如果SLEEPONEXIT位被置位,系统从最低优先级的中断处理程序中退出时,微控制器就立即进入睡眠模式。

2. 唤醒睡眠模式

  1. 如果执行WFI指令进入睡眠模式,任意一个被嵌套向量中断控制器响应的外设中断都能将系统从睡眠模式唤醒。
  2. 如果执行WFE指令进入睡眠模式,则一旦发生唤醒事件时,微处理器都将从睡眠模式退出。产生方式:
      在外设控制寄存器中使能一个中断,而不是在NVIC(嵌套向量中断控制器)中使能,并且在Cortex-M3系统控制寄存器中使能SEVONPEND位。当MCU从WFE中唤醒后,外设的中断挂起位和外设的NVIC中断通道挂起位(在NVIC中断清除挂起寄存器中)必须被清除。
      配置一个外部或内部的EXIT线为事件模式。当MCU从WFE中唤醒后,因为与事件线对应的挂起位未被设置,不必清除外设的中断挂起位或外设的NVIC中断通道挂起位。
    注:Cortex-M3 权威指南第13章(182-183页)也有讲解。

(二)停止模式

电源控制(PWR)   停止模式是在Cortex™-M3的深睡眠模式基础上结合了外设的时钟控制机制,在停止模式下电压调节器可运行在正常或低功耗模式。此时在1.8V供电区域的的所有时钟都被停止,PLL、HSI和HSE RC振荡器的功能被禁止,SRAM和寄存器内容被保留下来。在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。
1. 进入
  在停止模式下,通过设置 的LPDS位使内部调节器进入低功耗模式,能够降低更多的功耗。
  如果正在进行闪存编程,直到对内存访问完成,系统才进入停止模式。
  如果正在进行对APB的访问,直到对APB访问完成,系统才进入停止模式。
   ●独立看门狗(IWDG):可通过写入看门狗的键寄存器或硬件选择来启动IWDG。一旦启动了独立看门狗,除了系统复位,它不能再被停止。
  ● 实时时钟(RTC):通过备份域控制寄存器 (RCC_BDCR)的RTCEN位来设置。
  ● 内部RC振荡器(LSI RC):通过控制/状态寄存器 (RCC_CSR)的LSION位来设置。
  ● 外部32.768kHz振荡器(LSE):通过备份域控制寄存器 (RCC_BDCR)的LSEON位设置。在停止模式下,如果在进入该模式前ADC和DAC没有被关闭,那么这些外设仍然消耗电流。通过设置寄存器ADC_CR2的ADON位和寄存器DAC_CR的ENx位为0可关闭这2个外设。
2. 退出停止模式
  当一个中断或唤醒事件导致退出停止模式时,HSI RC振荡器被选为系统时钟。
当电压调节器处于低功耗模式下,当系统从停止模式退出时,将会有一段额外的启动延时。如果在停止模式期间保持内部调节器开启,则退出启动时间会缩短,但相应的功耗会增加。

(三)待机模式

电源控制(PWR)   待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。
 1. 进入
  可以通过设置独立的控制位,选择以下待机模式的功能:
  ● 独立看门狗(IWDG):可通过写入看门狗的键寄存器或硬件选择来启动IWDG。一旦启动了独立看门狗,除了系统复位,它不能再被停止。
  ● 实时时钟(RTC):通过备用区域控制寄存器(RCC_BDCR)的RTCEN位来设置。
  ● 内部RC振荡器(LSI RC):通过控制/状态寄存器(RCC_CSR)的LSION位来设置。
  ● 外部32.768kHz振荡器(LSE):通过备用区域控制寄存器(RCC_BDCR)的LSEON位设置。
 2. 退出待机模式
  当一个外部复位(NRST引脚)、IWDG复位、WKUP引脚上的上升沿或RTC闹钟事件的上升沿发生时(见图154 简化的RTC框图),微控制器从待机模式退出。从待机唤醒后,除了 : 电源控制/状态寄存器(PWR_CSR),所有寄存器被复位。
从待机模式唤醒后的代码执行等同于复位后的执行(采样启动模式引脚、读取复位向量等)。电源控制/状态寄存器(PWR_CSR)将会指示内核由待机状态退出。
3.待机模式下的输入/输出端口状态
  在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚:
  ● 复位引脚(始终有效)
  ● 当被设置为防侵入或校准输出时的TAMPER引脚
  ● 被使能的唤醒引脚

实现待机模式功能

1.初始化先进入待机状态,
2.当有按键按下进入运行模式,
3.在有按键按下3s又会进入待机模式,等到按键按下唤醒。
具体步骤:

  1. 使能电源时钟(是没次必不可少的)
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能 PWR 外设时钟`
  1. 设置PA0按键引脚作为唤醒源。
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
  1. 设置 SLEEPDEEP 位,置 设置 PDDS 位,执行 WFI 指令,进入待机模式。
void PWR_EnterSTANDBYMode(void);
  1. 编写按键中断函数。
void EXTI0_IRQHandler(void)
{
  EXTI_ClearITPendingBit(EXTI_Line0); // 清除 LINE10 上的中断标志位  
  if(Check_WKUP()==2) //进入待机模式
  {
    mode= 0;//清零模式变量
    Sys_Enter_Standby();
  }
  }

完整程序

/*
  1.初始化先判断data为0,就是待机状态,
  2.当有按键按下30ms进入运行模式,
  3.在有按键按下3s会进入睡眠模式 
   1-> 2->3->2->3 循环
     硬件: PA0接下拉的按键;PB5接共阳LED(0亮1灭)
     MCU:STM32F103ZETx系列
*/
#include "stm32f10x.h"    
u8 mode=0; //待机、唤醒模式控制变量      
void delay_ms(u16 time)
{    
   u16 i = 0;  
   while(time--)
   {
      i = 12000;  
      while(i--);    
   }
}
//初始化PB5  LED灯
void LED_Init_PB5(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  GPIO_InitTypeDef GPIO_ITDef_PB5; 
  GPIO_ITDef_PB5.GPIO_Pin = GPIO_Pin_5;
  GPIO_ITDef_PB5.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出  
  GPIO_ITDef_PB5.GPIO_Speed = GPIO_Speed_2MHz;  
  GPIO_Init(GPIOB,&GPIO_ITDef_PB5);
  GPIO_SetBits(GPIOB,GPIO_Pin_5);// 置 1输出高电平
//  GPIO_ResetBits(GPIOB,GPIO_Pin_5);// 0
}

u8 Check_WKUP(void)
{
  u8 t=0;
  u8 tx=0; //记录松开的次数
  GPIO_ResetBits(GPIOB,GPIO_Pin_5);// 置1  LED亮 
  while(1)
 {   
    if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//已经按下了 
     delay_ms(5);//按键延时消斗
    if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//已经按下了
    {
       t++;
       tx=0;
    }
    else
     {   
        tx++;//超过300ms内没有WKUP信号
       if(tx>1)
       {
         GPIO_SetBits(GPIOB,GPIO_Pin_5);//1
         return 0;//错误的按键,按下次数不够
       }       
      }        
   delay_ms(30);
   if(mode== 0)
     {
        return mode=1;//有按键按下,唤醒待机模式
     }         
   if(t>=100&&mode== 1)//按下超过3秒钟
      {
        GPIO_ResetBits(GPIOB,GPIO_Pin_5);// 0点亮 DS0
        return mode=2; //按下 3s 以上了,进入待机模式 
      }
 }
}
void WKUP_Init(void)
{
  //PA0(KEY中断)作为唤醒条件
      //使能 GPIOA 和复用功能时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
  //初始化PA0的按键(上拉输入)
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;//PA.0
  GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD; //上拉输入
  GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 IO  
  //使用按键外部中断方式
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
  //中断线 0 连接 GPIOA. (按键)
  EXTI_InitTypeDef EXTI_InitStructure;
  EXTI_InitStructure.EXTI_Line = EXTI_Line0; //设置按键所有的外部线路
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //外部中断模式
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure); // 初始化外部中断
    //按键中断设置
  NVIC_InitTypeDef   NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//先占优先级 2 级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//从优先级 2 级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//外部中断通道使能
  NVIC_Init(&NVIC_InitStructure);//初始化 NVIC    
}

//系统进入待机模式
void Sys_Enter_Standby(void)
{
  RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //复位所有 IO 口  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能PWR外设时钟
  PWR_WakeUpPinCmd(ENABLE);//使能唤醒管脚功能
  PWR_EnterSTANDBYMode();//进入待命(STANDBY)模式
}
//中断,检测到 PA0 脚的一个上升沿.
//中断线 0 线上的中断检测
void EXTI0_IRQHandler(void)
{
  EXTI_ClearITPendingBit(EXTI_Line0); // 清除 LINE10 上的中断标志位  
  if(Check_WKUP()==2) //进入待机模式
  {
    mode= 0;//清零模式变量
    Sys_Enter_Standby();
  }
}
int main(void)
{
  LED_Init_PB5();
  WKUP_Init(); //待机唤醒初始化
  if(Check_WKUP()==1)  //不是开机,进入待机模式
  {
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能PWR外设时钟
    PWR_WakeUpPinCmd(ENABLE);//使能唤醒管脚功能
    PWR_EnterSTANDBYMode();//进入待命(STANDBY)模式
  }
  while(1)
  {
     GPIO_ResetBits(GPIOB,GPIO_Pin_5);//LED亮
     delay_ms(50);        
     GPIO_SetBits(GPIOB,GPIO_Pin_5);//LED灭
     delay_ms(50);   
  }   
}

常用资料:
  STM32F10x_StdPeriph_Lib_V3.5.0(官方固件库)
  链接:STM32固件库使用手册的中文翻译版 提取码:4lkx

猜你喜欢

转载自blog.csdn.net/weixin_43993734/article/details/101423336
今日推荐