预备
- stm32L0系列的低功耗有Low-power run,Sleep,Low-power sleep, Stop, Standby等5种模式, 其中standby模式最省电, 但是注意该模式会使芯片掉内存的数据, 而stop模式,只是将CPU,时钟等停止(不包括LSE,LSI时钟), ram的数据依然能被保存。
- 低功耗模式中除了低功耗运行模式之外 Low-power modes (except for Low-power run mode) 都通过执行
WFI(Wait For Interrupt)
或者WFE (Wait for Event)
指令来进入低功耗模式, 该指令会停止mcu核心来节省电量, 然后等待唤醒中断或者事件。 - 芯片进入低功耗模式之后, 就只能通过串口来烧写程序了,
SWD调试也被关闭了。
- 将所有引脚配置为 LL_GPIO_MODE_ANALOG模式, 可以避免引脚开启施密特触发器以及上拉,下拉带来的电量损耗,但是注意
该配置会将引脚功能重映射, 使得SWD调试无法进行,此时 只能通过串口进行代码调试
。 - 芯片初步启动的时候由MSI的时钟来执行跳转配置时钟等程序,时钟配置之后才切换生效。
代码
- 其实没什么难度, 直接查看配置代码吧。
- 配置引脚为anglog模式:
void ReduceIOPowerConsumption(void){
LL_GPIO_InitTypeDef gpio_initstruct = {LL_GPIO_PIN_ALL, LL_GPIO_MODE_ANALOG,
LL_GPIO_SPEED_FREQ_HIGH, LL_GPIO_OUTPUT_PUSHPULL,
LL_GPIO_PULL_NO, LL_GPIO_AF_0};
/* Set all GPIO in analog state to reduce power consumption, */
/* Note: Debug using ST-Link is not possible during the execution of this */
/* example because communication between ST-link and the device */
/* under test is done through UART. All GPIO pins are disabled (set */
/* to analog input mode) including UART I/O pins. */
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA |
LL_IOP_GRP1_PERIPH_GPIOB |
LL_IOP_GRP1_PERIPH_GPIOC);
LL_GPIO_Init(GPIOA, &gpio_initstruct);
LL_GPIO_Init(GPIOB, &gpio_initstruct);
LL_GPIO_Init(GPIOC, &gpio_initstruct);
LL_IOP_GRP1_DisableClock(LL_IOP_GRP1_PERIPH_GPIOA |
LL_IOP_GRP1_PERIPH_GPIOB |
LL_IOP_GRP1_PERIPH_GPIOC );
}
- 进入停止模式:
**
* @brief Function to configure and enter in STOP Mode.
* @param None
* @retval None
*/
void EnterSTOPMode(void)
{
//ReduceIOPowerConsumption();
/** Request to enter STOP mode
* Following procedure describe in STM32L0xx Reference Manual
* See PWR part, section Low-power modes, STOP mode
*/
/* Enable ultra low power mode */
LL_PWR_EnableUltraLowPower();
/** Set the regulator to low power before setting MODE_STOP.
* If the regulator remains in "main mode",
* it consumes more power without providing any additional feature. */
LL_PWR_SetRegulModeLP(LL_PWR_REGU_LPMODES_LOW_POWER);
/* Set STOP mode when CPU enters deepsleep */
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP);
/* Set SLEEPDEEP bit of Cortex System Control Register */
LL_LPM_EnableDeepSleep();
/* Request Wait For Interrupt */
__WFI();
}
- 配置RTC中断唤醒:
/**
* @brief Configure RTC
* @param void
* @retval None
*/
void Configure_RTC(int wu_sec)
{
/*##-1- Enables the PWR Clock and Enables access to the backup domain #######*/
/* To change the source clock of the RTC feature (LSE, LSI), you have to:
- Enable the power clock
- Enable write access to configure the RTC clock source (to be done once after reset).
- Reset the Back up Domain
- Configure the needed RTC clock source */
LL_PWR_EnableBkUpAccess();
/*##-2- Configure LSE as RTC clock source ###############################*/
/* Enable LSE only if disabled.*/
if (LL_RCC_LSE_IsReady() == 0)
{
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_LSE_Enable();
while (LL_RCC_LSE_IsReady() != 1)
{
}
}
/* Choose LSE to */
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
/*##-3- Enable RTC peripheral Clocks #######################################*/
/* Enable RTC Clock */
LL_RCC_EnableRTC();
/*##-4- Disable RTC registers write protection ##############################*/
LL_RTC_DisableWriteProtection(RTC);
/*##-5- Enter in initialization mode #######################################*/
if (Enter_RTC_InitMode() != RTC_ERROR_NONE)
{
printf("RTC enter init error\r");
}
/*##-6- Configure RTC ######################################################*/
/* Configure RTC prescaler and RTC data registers */
/* Set Hour Format */
LL_RTC_SetHourFormat(RTC, LL_RTC_HOURFORMAT_24HOUR);
/* Set Asynch Prediv (value according to source clock) */
LL_RTC_SetAsynchPrescaler(RTC, RTC_ASYNCH_PREDIV);
/* Set Synch Prediv (value according to source clock) */
LL_RTC_SetSynchPrescaler(RTC, RTC_SYNCH_PREDIV);
/* Set OutPut */
/* Reset value is LL_RTC_ALARMOUT_DISABLE */
//LL_RTC_SetAlarmOutEvent(RTC, LL_RTC_ALARMOUT_DISABLE);
/* Set OutPutPolarity */
/* Reset value is LL_RTC_OUTPUTPOLARITY_PIN_HIGH */
//LL_RTC_SetOutputPolarity(RTC, LL_RTC_OUTPUTPOLARITY_PIN_HIGH);
/* Set OutPutType */
/* Reset value is LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN */
//LL_RTC_SetAlarmOutputType(RTC, LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN);
/*##-7- Exit of initialization mode #######################################*/
Exit_RTC_InitMode();
/* Disable wake up timer to modify it */
LL_RTC_WAKEUP_Disable(RTC);
/* Wait until it is allow to modify wake up reload value */
while (LL_RTC_IsActiveFlag_WUTW(RTC) != 1)
{
}
/* Setting the Wakeup time to 1 s
If LL_RTC_WAKEUPCLOCK_CKSPRE is selected, the frequency is 1Hz,
this allows to get a wakeup time equal to 1 s if the counter is 0x0 */
LL_RTC_WAKEUP_SetAutoReload(RTC, wu_sec);
LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);
/* Enable wake up counter and wake up interrupt */
LL_RTC_WAKEUP_Enable(RTC);
LL_RTC_EnableIT_WUT(RTC);
/*##-8- Enable RTC registers write protection #############################*/
LL_RTC_EnableWriteProtection(RTC);
/* Configure exti and nvic for RTC IT */
LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_20);
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_20);
NVIC_SetPriority(RTC_IRQn, 0);
NVIC_EnableIRQ(RTC_IRQn);