STM32L0系列之02 RTC唤醒待机模式

前言

使用芯片:STM32L051R8T6
软件平台:KEIL V5、STM32CubeL0
库函数:HAL

一、硬件介绍

1、单片机的系统时钟为:32Mhz,由PLL时钟提供
2、PLL通过8MHz的高速外部晶振(HSE)经过8倍频,2分频后得到
3、RTC始终源选择32.768KMz的石英晶体振荡器(LSE),是的RTC在停机和待机两种低功耗模式下工作,并可以用作唤醒源;
4、如果 RTC 的时钟由 LSE 提供,则 RTC 在系统复位后仍可获得时钟并保持正常工作。

二、待机模式介绍

1、待机模式下I/O状态

在待机模式下,除以下各部分以外,所有 I/O 引脚都处于高阻态:
(1) 复位引脚
(2)唤醒引脚(WKUP1、 WKUP2、 WKUP3)
(3)以下 I/O 上的 RTC 功能(入侵、时间戳、 RTC 闹钟输出、 RTC 时钟校准输出):
– 类别 3: PC13、 PA0
– 类别 5: PC13、 PA0、 PE6

2、进入待机模式

  PDDS 位 +SLEEPDEEP 位 +WFI,从 ISR 返回或 WFE

3、退出待机模式

WKUP 引脚上升沿、RTC 闹钟(闹钟 A 或闹钟 B)、 RTC 唤醒事件、RTC 入侵事件、RTC 时间戳事件、NRST 引脚外部复位、IWDG 复位

三、程序代码

1、 系统时钟配置

void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};/**Configure the main internal regulator output voltage */__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/**Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;//RCC_OscInitStruct.HSIState = RCC_HSI_ON; //ADC的时钟源RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8;RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/**Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}

2、 RTC时钟配置

void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
{RCC_OscInitTypeDef RCC_OscInitStruct;RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;/*##-1- Configue the RTC clock soucre ######################################*/
#ifdef RTC_CLOCK_SOURCE_LSE/* -a- Enable LSE Oscillator */RCC_OscInitStruct.OscillatorType =  RCC_OSCILLATORTYPE_LSE;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;RCC_OscInitStruct.LSEState = RCC_LSE_ON;if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){ while(1);}/*##-2- Enable the RTC peripheral Clock ####################################*//* Enable RTC Clock */__HAL_RCC_RTC_ENABLE();/*##-3- Configure the NVIC for RTC Alarm ###################################*/HAL_NVIC_SetPriority(RTC_IRQn, 0x0, 0);HAL_NVIC_EnableIRQ(RTC_IRQn);
}

3、 RTC初始化配置配置

void SystemPower_Config(void)
{__HAL_RCC_PWR_CLK_ENABLE(); HAL_PWREx_EnableUltraLowPower();/* Enable the fast wake up from Ultra low power mode */HAL_PWREx_EnableFastWakeUp();/* Configure RTC */RTCHandle.Instance = RTC;/* Set the RTC time base to 1s *//* Configure RTC prescaler and RTC data registers as follow:- Hour Format = Format 24- Asynch Prediv = Value according to source clock- Synch Prediv = Value according to source clock- OutPut = Output Disable- OutPutPolarity = High Polarity- OutPutType = Open Drain */RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;HAL_RTC_Init(&RTCHandle) ;__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);	// 清除唤醒标志__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);	// 清除待机标志HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 8192, RTC_WAKEUPCLOCK_RTCCLK_DIV16);__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);}

写程序的时候忘记配置 __HAL_RCC_PWR_CLK_ENABLE(); 导致RTC不能正常工作

4、 进入待机模式

void LowPower_enter_standby(void)
{printf("=== Power standby ===\r\n");HAL_Delay(50);//UART1;	减少16uAHAL_UART_MspDeInit(&huart);HAL_UART_MspDeInit(&huart2);__HAL_RCC_GPIOA_CLK_DISABLE();__HAL_RCC_GPIOB_CLK_DISABLE();__HAL_RCC_GPIOC_CLK_DISABLE();__HAL_RCC_GPIOH_CLK_DISABLE();// 禁用 调试端口 少800uA,下面2句函数功能一样!//HAL_DBGMCU_DisableDBGStandbyMode();HAL_DBGMCU_DBG_DisableLowPowerConfig(DBGMCU_SLEEP | DBGMCU_STOP | DBGMCU_STANDBY);// 若需要在低功耗模式下调试程序,可以打开此函数//HAL_DBGMCU_DBG_EnableLowPowerConfig(DBGMCU_SLEEP | DBGMCU_STOP | DBGMCU_STANDBY);// PIN1 连接到 PWR->CR 的 PWR_FLAG_WU 标记// 用于待机模式IO唤醒,唤醒后判断WKUP按钮状态//		WKUP pin 1 (PA00) if enabled.//      WKUP pin 2 (PC13) if enabled.//      WKUP pin 3 (PE06) if enabled, for stm32l07xxx and stm32l08xxx devices only.//      WKUP pin 3 (PA02) if enabled, for stm32l031xx devices only.HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);	// 清除唤醒标志__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);	// 清除待机标志/*## Setting the RTC Wake up time ########################################*//*  RTC Wakeup Interrupt Generation:Wakeup Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSE or LSI))Wakeup Time = Wakeup Time Base * WakeUpCounter= (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSE or LSI)) * WakeUpCounter==> WakeUpCounter = Wakeup Time / Wakeup Time BaseTo configure the wake up timer to 4s the WakeUpCounter is:RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16Wakeup Time Base = 16 /(~32768Hz) = ~488.3usWakeup Time = ~4s = 0,410ms  * WakeUpCounter==> WakeUpCounter = 4s/488.3us = 8192  */
#ifdef __rtc_H// 该功能可以用Cubme RTC内配置,代码可以参考rtc.c文件内// rtc 唤醒采用LSE时钟,第一参数,计数溢出唤醒;第二参数:进行16分配HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 8192, RTC_WAKEUPCLOCK_RTCCLK_DIV16);__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
#endif/* Enter Standby Mode */HAL_PWR_EnterSTANDBYMode();}

三、测试结果