STM32GX低功耗学习笔记一
最近要用到低功耗功能,看了下手册,把学习过程记录下,其中也有一些不明白的地方期望和大家进行交流。
首先来看看低功耗模式有哪些:
再看看怎么进入低功耗:
在这里我选择了STOP0模式:
在这里,我有一点疑惑就是进入STOP0之前,手册说不能有事件或者中断位产生,否则就不能进入低功耗模式
而是继续运行。这里怎么避免产生事件或者中断位?
上代码:
1、使能PWR时钟
/*##-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_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
LL_PWR_EnableBkUpAccess();
2、配置RTC
static void rtc_init(void)
{
if(!LL_RCC_LSI_IsReady()){
LL_RCC_LSI_Enable();
NOP();
NOP();
NOP();
NOP();
while(!LL_RCC_LSI_IsReady());//Èý¸öLSIÖÜÆÚÖ®ºó²Å¸üÐÂ
}
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
LL_RTC_InitTypeDef RTC_InitStruct = {0};
LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
LL_RTC_DateTypeDef RTC_DateStruct = {0};
LL_RTC_AlarmTypeDef RTC_AlarmStruct = {0};
/* Peripheral clock enable */
LL_RCC_EnableRTC();
/* USER CODE BEGIN RTC_Init 1 */
/* Enable RTC APB clock */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTC);
/* USER CODE END RTC_Init 1 */
RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
RTC_InitStruct.AsynchPrescaler = RTC_ASYNCH_PREDIV;
RTC_InitStruct.SynchPrescaler = RTC_SYNCH_PREDIV;
LL_RTC_Init(RTC, &RTC_InitStruct);
RTC_TimeStruct.Hours = 0x12;
RTC_TimeStruct.Minutes = 0x00;
RTC_TimeStruct.Seconds = 0x00;
LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_TimeStruct);
RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_FRIDAY;
RTC_DateStruct.Month = LL_RTC_MONTH_DECEMBER;
RTC_DateStruct.Day = 0x29;
RTC_DateStruct.Year = 0x16;
LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_DateStruct);
/** Enable the Alarm A
*/
RTC_AlarmStruct.AlarmTime.Hours = 0x12;
RTC_AlarmStruct.AlarmTime.Minutes = 0x00;
RTC_AlarmStruct.AlarmTime.Seconds = 0x05;
RTC_AlarmStruct.AlarmMask = LL_RTC_ALMA_MASK_DATEWEEKDAY;
RTC_AlarmStruct.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
RTC_AlarmStruct.AlarmDateWeekDay = 0x1;
LL_RTC_ALMA_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_AlarmStruct);
/* USER CODE BEGIN RTC_Init 2 */
/* Disable the write protection for RTC registers */
LL_RTC_DisableWriteProtection(RTC);
/* Enable Alarm*/
LL_RTC_ALMA_Enable(RTC);
/* Clear the Alarm interrupt pending bit */
LL_RTC_ClearFlag_ALRA(RTC);
/* Enable IT Alarm */
LL_RTC_EnableIT_ALRA(RTC);
/* Enable the write protection for RTC registers */
LL_RTC_EnableWriteProtection(RTC);
/* RTC Alarm Interrupt Configuration: EXTI configuration */
LL_EXTI_ClearRisingFlag_0_31 (LL_EXTI_LINE_19);
LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_19);
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_19);
/*## Configure the NVIC for RTC Alarm ##################################*/
NVIC_SetPriority(RTC_TAMP_IRQn, 0x0F);
NVIC_EnableIRQ(RTC_TAMP_IRQn);
/* USER CODE END RTC_Init 2 */
}
3、中断配置
void RTC_TAMP_IRQHandler(void)
{
/* Get the Alarm interrupt source enable status */
static uint8_t i=1;
if (LL_RTC_IsEnabledIT_ALRA(RTC) != 0)
{
/* Get the pending status of the Alarm Interrupt */
if (LL_RTC_IsActiveFlag_ALRA(RTC) != 0)
{
/* Alarm callback */
//Alarm_Callback();
SystemClock_Config();
TRACE_INFO("RTC=%d\r\n",i);
i++;
/* Clear the Alarm interrupt pending bit */
LL_RTC_ClearFlag_ALRA(RTC);
}
}
/* Clear the EXTI's Flag for RTC Alarm */
LL_EXTI_ClearFallingFlag_0_31(LL_EXTI_LINE_19);
}
4、进入STOP0模式
LL_RTC_ClearFlag_ALRA(RTC);
LL_EXTI_ClearRisingFlag_0_31 (LL_EXTI_LINE_19);
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
//LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);
LL_LPM_EnableDeepSleep();
//LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
#if defined ( __CC_ARM)
__force_stores();
#endif
//__WFE();
__WFI();
这里有一点问题,就是WIE不起作用,目前没有想明白。
如果是进入STANDBY模式,仅仅把LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
修改为LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);即可
经过试验,得出如下结论:
1、STANDBY被RTC唤醒,则会复位;
2、STOP0被RTC唤醒,则会继续运行,但是时钟需要重新配置下。
目前能够休眠和唤醒了,哎,我也该睡觉了,困,剩下的问题以后找到答案再贴上来。。。。。。。