STM32有3中低功耗模式:
1)睡眠模式(CM3 内核停止,外设仍然运行)
2)停止模式(所有时钟都停止)
3)待机模式(1.8V 内核电源关闭)
在运行模式下,我们也可以通过降低系统时钟关闭 APB 和 AHB 总线上未被使用的外设的时钟来降低功耗。三种低功耗模式一览表见表 21.1.1 所示
在这三种模式中,最低功耗的属于第三种模式,即待机模式,最低只需要2uA的电流。停机模式是次低功耗的,其典型的电流消耗在 20uA 左右。最后就是睡眠模式了。
下边就讲一下待机模式如何进入以及如何运行。该模式是在 CM3 深睡眠模式时关闭电压调节器。整个 1.8V 供电区域被断电。PLL、HSI 和 HSE 振荡器也被断电。SRAM 和寄存器内容丢失。仅备份的寄存器和待机电路维持供电。
void Sys_Standby(void)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR外设时钟。因为低功耗模式属于电源管理的一部分,要进入低功耗模 式就需要对PWR相关的寄存器进行相关的设置。要操作寄存器首先就要打开时钟。 PWR是挂载在APB1总线下的。
PWR_WakeUpPinCmd(ENABLE);//使能唤醒引脚功能----->打开开关。 //Enables or disables the WakeUp Pin functionality.
PWR_EnterSTANDBYMode(); //调用库函数,进入待机模式【】。此函数在stm32f10x_pwr.c中。
/******************************************************************************
这是库中的原型。进入的那几个步骤。
void PWR_EnterSTANDBYMode(void)
{
// Clear Wake-up flag
PWR->CR |= PWR_CR_CWUF;
/* Select STANDBY mode,掉电深睡眠模式-----PDDS位置1 */
PWR->CR |= PWR_CR_PDDS;
/* Set SLEEPDEEP bit of Cortex System Control Register */
//进入待机模式, 首先要设置 SLEEPDEEP 位(该位在系统控制寄存器(SCB_SCR)的第二位,最后执行 WFI 指令开始进入待机模式,并等待 WK_UP中断的到来。
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM )
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
******************************************************************************/
}
//进入待机模式
void Sys_Enter_Standby(void)
{
RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //¸复位福所有的IO
Sys_Standby();
}
//检测WKUP引脚的信号
//返回1:连续按下3S钟以上
// 返回0:错误的触发
unsigned char check(void)
{
unsigned char t = 0;//记录按下的时间
//LED0 --->PB0
GPIO_ResetBits(GPIOB,GPIO_Pin_5);//打开LED0
while(1)
{
if(1 == GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) )//WKUP按下---WKUP ---PA0
{
t++;
delay_ms(30);
if(t>=100)//3s钟到了
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5);//LED0亮,返回1
return 1;
}
}else
{
GPIO_SetBits(GPIOB,GPIO_Pin_5); //LED0灭,返回0
return 0;//
}
}
}
//中断服务函数 使用中断线0
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0); //清除中断线0上的标志位
if(check())//检测是否关机?
{
Sys_Enter_Standby();
}
}
void WKUP_Init(void)
{
GPIO_InitTypeDef GPIO_Instructure1;
NVIC_InitTypeDef NVIC_Instructure;
EXTI_InitTypeDef EXIT_Instructure;
//时钟使能 GPIOA挂载在APB2的总线下。要设置那个GPIO pin被用于中断线就要打开AFIO时钟。 这里一同打开。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
GPIO_Instructure1.GPIO_Pin = GPIO_Pin_0;//PA.0
GPIO_Instructure1.GPIO_Mode = GPIO_Mode_IPD;//上拉输入
GPIO_Init(GPIOA,&GPIO_Instructure1);//初始化IO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
//设置GPIOA0作为中断线
EXIT_Instructure.EXTI_Line = EXTI_Line0;//中断线0
EXIT_Instructure.EXTI_Mode = EXTI_Mode_Interrupt;//使用中断模式而不是事件模式
EXIT_Instructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
EXIT_Instructure.EXTI_LineCmd =ENABLE;//使能中断命令
EXTI_Init(&EXIT_Instructure);//初始化外部中断
//
NVIC_Instructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键所在的外部中断通道
NVIC_Instructure.NVIC_IRQChannelSubPriority = 2; //先优先级2级
NVIC_Instructure.NVIC_IRQChannelPreemptionPriority = 2;//´子优先级2级
NVIC_Instructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_Instructure);//根据NVIC_Instructure所设置的参数初始化NVIC寄存器
if(check()==0)
Sys_Standby(); //不是开机,是进入待机模式
}
int main(void)
{
SystemInit(); //我配置的时钟有点问题,在这里调用系统时钟使之到72M。
delay_init();
LED_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2,2位抢占优先级,2位响应优先级。
WKUP_Init();
while (1)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_5, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_5))));
delay_ms(1000);
}
return 0;
}
刚开始学习,个人的一点总结。有不对的地方欢迎大家指针批评。