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(); //进入待机模式
}
}
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(); //进入待机模式
}
}
举报