STM32
直播中

纯纯纯牛奶

11年用户 523经验值
私信 关注
[问答]

STM32具有哪几种待机模式? 待机唤醒配置步骤是怎样的?

STM32具有哪几种待机模式?待机唤醒配置步骤是怎样的?

回帖(1)

张楠

2021-11-18 15:28:25
STM32的3种低功耗模式
①睡眠模式:内核停止,外设比如NVIC,系统时钟Systick仍然运行
②停止模式:所有时钟停止,1.8V内核电源工作
③待机模式:1.8V内核电源关闭;只有备份寄存器和待机威廉希尔官方网站 维持供电,寄存器和SRAM内容丢失,功耗最低
  运行模式下降低功耗:降低系统时钟,关闭APB,AHB总线上的未使用外设时钟
STM32待机模式






  进入待机模式前,对于使用了RTC闹钟中或者RTC周期性唤醒中断的时候,需要处理
  

  • a) 禁止 RTC 闹钟中断(RTC_CR 寄存器中的 ALRAIE 或 ALRBIE 位)
  • b) 将 RTC 闹钟 (ALRAF/ALRBF) 标志清零
  • c) 将 PWR 唤醒 (WUF) 标志清零
  • d) 使能 RTC 闹钟中断
  • e) 重新进入低功耗模式

待机唤醒配置步骤:
①使能电源时钟:RCC_APB1PeriphClockCmd();
②RTC相关处理:关闭RTC相关中断
③设置WK_UP引脚作为唤醒源
设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒
PWR_WakeUpPinCmd();
④设置SLEEPDEEP位,设置PDDS位,执行WFI指令,进入待机模式
PWR_EnterSTANDBYMode();

//系统进入待机模式
void Sys_Enter_Standby(void)
{
       
        while(WKUP_KD);                        //等待WK_UP按键松开(在有RTC中断时,必须等WK_UP松开再进入待机)
        RCC_AHB1PeriphResetCmd(0X04FF,ENABLE);                   //复位所有IO口   =这一步暂时不清楚
       
        //使能电源时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能 PWR 外设时钟
        PWR_BackupAccessCmd(ENABLE);                            //后备区域访问使能
       
        /*RTC相关处理进行清零:1)禁止 RTC 闹钟中断(RTC_CR 寄存器中的 ALRAIE 或 ALRBIE 位)
                                                  2)将 RTC 闹钟 (ALRAF/ALRBF) 标志清零
                                                  3)将 PWR 唤醒 (WUF) 标志清零                                  */       
        RTC_ITConfig(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA,DISABLE);   //关闭RTC相关中断,可能在RTC实验打开了,
        RTC_ClearITPendingBit(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA);   //清楚RTC相关标志位,比如RTC入侵,RTC唤醒       
        PWR_ClearFlag(PWR_FLAG_WU);                    //清除Wake-up 标志,这个标志好像在唤醒后会置为1
       
                       
        //设置WK_UP引脚作为唤醒源,设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒
        PWR_WakeUpPinCmd(ENABLE);    //使能唤醒管脚功能,设置 PWR_CSR 的 EWUP 位,使能 WK_UP 用于将 CPU 从待机模式唤醒
               
       
        //设置SLEEPDEEP位,设置PDDS位,执行WGI指令,进入待机模式       
        PWR_EnterSTANDBYMode();        //进入待机模式               
}




//检测WKUP脚的信号
//返回值1:连续按下3s以上
//      0:错误的触发       
u8 Check_WKUP(void)
{
        u8 t=0;
        u8 tx=0;//记录松开的次数
        LED0=0; //亮灯DS0
        while(1)
        {
                if(WKUP_KD)//已经按下了
                {
                        t++;
                        tx=0;
                }else
                {
                        tx++;
                        if(tx>3)//超过90ms内没有WKUP信号
                        {
                                LED0=1;
                                return 0;//错误的按键,按下次数不够
                        }
                }
                delay_ms(30);
                if(t>=100)//按下超过3秒钟
                {
                        LED0=0;          //点亮DS0
                        return 1; //按下3s以上了
                }
        }
}




//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{          
        GPIO_InitTypeDef   GPIO_InitStructure;
        NVIC_InitTypeDef   NVIC_InitStructure;
        EXTI_InitTypeDef   EXTI_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                 //PA0
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;              //输入模式
        GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;                   //开漏
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;             //下拉
        GPIO_Init(GPIOA, &GPIO_InitStructure);                    //初始化       


        //(检查是否是正常开机 )                    
        if(Check_WKUP()==0)
        {
                Sys_Enter_Standby();        //不是正常唤醒,进入待机模式  
        }
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PA0 连接到中断线0
         
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;             //LINE0
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;    //中断事件
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;              //使能LINE0
        EXTI_Init(&EXTI_InitStructure);//配置       
       
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
        NVIC_Init(&NVIC_InitStructure);//配置NVIC


}




//中断,检测到PA0脚的一个上升沿.          
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{                                                                                                  
    EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
        if(Check_WKUP())   //关机?
        {                  
                Sys_Enter_Standby(); //进入待机模式
        }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分