STM32F0的低功耗模式
STM32的低功耗模式有三种, STOP, SLEEP, STANDBY.
其中SLEEP没啥用, 好处是一戳就醒.
最低功耗是STANDBY模式, 据说只有2ua电流, 但是每次醒来, 就相当于重启了, SRAM全重置, 另外一个坏处是需要指定一个PA0脚, 即WAKEUP脚的上升沿唤醒.
最好用的应该就是这个STOP模式, 寄存器跟SRAM都保存状态, 连IO都保持, 唤醒的方法是外部中断跟通讯, 通讯还没测试, 外部中断是ok了.
进中断的方法很简单:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_SLEEPEntry_WFI);
但是之前要设置要外部中断, 比如一个按键:
GPIO_InitTypeDef GPIO_InitStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_2; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStruct); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource12); EXTI_ClearITPendingBit(EXTI_Line12); EXTI_InitStruct.EXTI_Line = EXTI_Line12; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = EXTI4_15_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct);
为了防止醒来之后时钟的问题:
void SYSCLKConfig_STOP(void) { /* After wake-up from STOP reconfigure the system clock */ /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {} /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {} /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while (RCC_GetSYSCLKSource() != 0x08) {} }
结果这里发现一个问题, 我先是需要使用一个TIM来进行定时任务, 我的目标是, 如果系统空闲超过一段时间, 比如20秒, 就进入STOP模式, 结果发现在定时器的irq_hendle函数中, 无法进入低功耗, 没辙, 在main里面增加了一个全局变量, 用TIM将这个变量置, 在main的while循环中去进入STOP模式.
if(ifGotoStop){ printf("sleepy\r\n"); sysEnterStopMode(); //System_Init(); //TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); SYSCLKConfig_STOP(); printf("go out\r\n"); ifGotoStop = 0; }
唤醒的按键中断(增加了去抖):
void EXTI4_15_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line12)!=RESET) { while(TEST_KEY == RESET){ timeCounter++; } if(timeCounter > 10000){ printf("wake up! \r\n"); } timeCounter = 0; //LED05_OFF; } EXTI_ClearITPendingBit(EXTI_Line12); }
剩下的就是检查低功耗时候的电流, 以及增加串口输入的中断作为唤醒条件.