超低功耗研发-STM32L151C8T6芯片(三)RTC自动唤醒机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012351051/article/details/86701931

    超低功耗产品必然涉及到“唤醒”机制,唤醒后执行 正常的功能代码,这个“唤醒”动作有多种,基本上有外部中断、中断事件、RTC自动唤醒等,外部中断多是IO口中断,比如按键触发,而RTC自动中断相比较“智能”一些,倒计时一定时间后,自动唤醒CPU,所以RTC自动唤醒基本上就是 为超低功耗定制 的,用起来非常方便,先看下STM32L151的RTC系统时钟树:

    上图中的WUTR就是wake up auto-reload timer,即自动唤醒状态寄存器,而WUTF就是 wake up timerr function自动唤醒功能, 通过上图时钟树可知,RTC自动唤醒是一个16位的定时器(向下计数),数值范围自然是0~65535,也就是65536份,自动唤醒计时器的时钟来源有两种,分别是来自外部LSE(32.768khz)经过2、4、8、16分频,或者经过ck_apre和ck_spre分频,其中经过ck_apre和ck_spre分频出的频率默认为1HZ,从这一点就能看出来,这不是巧合,是故意设定的,方便工程师使用,在这种模式下,自动唤醒时间可以设定为1~65536s(18小时),如果这个时间还不够,还可以通过软件配置,达到18h~36h,

      RTC的自动唤醒需要配合对应中断,才能唤醒CPU,手册上提到的是,所有的RTC中断(闹钟、自动唤醒、时间戳)内部都连接到了EXTI控制器上,如果使能RTC 唤醒中断,需要的操作如下:

     ① 配置EXTI Line20 中断,选择rising edge触发。

     ② 配置使能RTC_WKUP IRQ 通道,在NVIC中。

     ③ 配置RTC 产生RTC wakeup 计数器事件。

RTC自动唤醒功能配置代码如下:

void RTC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  EXTI_InitTypeDef EXTI_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  //allow access to rtc
  PWR_RTCAccessCmd(ENABLE);
  //RESET RTC Domain
  RCC_RTCResetCmd(ENABLE);
  RCC_RTCResetCmd(DISABLE);
  //LSE enable   32.768k
  RCC_LSEConfig(RCC_LSE_ON);
  //wait till LSE is ready
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {}
  //rtc clock select
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  //enable rtc clock
  RCC_RTCCLKCmd(ENABLE);
  // wait for rtc APB registers synchronisation
  RTC_WaitForSynchro();
  //EXIT Config
  EXTI_ClearITPendingBit(EXTI_Line20);
  EXTI_InitStructure.EXTI_Line = EXTI_Line20;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
  //enable the rtc wakeup interrupt
  NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  //rtc wakeup interrupt generation:clock source:RTCDiv_16,
  //wakeup time base:4s
  RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
  RTC_SetWakeUpCounter(10);
  //enable the wakeup interrupt
  RTC_ITConfig(RTC_IT_WUT, ENABLE);

}

   基本流程为:

   ① 使能PWR时钟。

   ② 取消RTC写保护。

   ③ 复位RTC

   ④ 使能LSE

   ⑤ 等待LSE就位

   ⑥ 选择RTC时钟源,肯定是选择LSE

   ⑦ 使能RTC时钟源

   ⑧ RTC同步就位

   ⑨ 配置EXTI_Line20,上升沿触发,并使能。

   ⑩ 配置wakeup  中断。

  (11)  选择RTC wakeup时钟源, 这里就选择了RTC_WakeUpClock_CK_SPRE_16bits,也就是选择1Hz时钟。

(12)设定wakeup 定时器装载数,这里设定为10,说明就是10s唤醒。

(12) 使能wakeup 中断

  进行初始化这些后,还需要编写wakeup  中断服务函数:

  

void RTC_WKUP_IRQHandler(void)
{
  if(RTC_GetITStatus(RTC_IT_WUT) != RESET)
  {
    RTC_ClearITPendingBit(RTC_IT_WUT);
    EXTI_ClearITPendingBit(EXTI_Line20);
  } 
}

   重点就是要清除WUT和EXTI_Line20中断标志。

   至此,RTC的自动唤醒机制已经搭建完成,但是此时还未触发自动唤醒,这个就需要在应用程序里,编写代码:

   

   /*使能自动唤醒功能 */
    RTC_WakeUpCmd(ENABLE);

    /*控制CPU进入stop模式 */
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);

    /* CPU唤醒后,先停止自动唤醒功能 */
    RTC_WakeUpCmd(DISABLE);
   //
   //
   //PLL 初始化
   //正常应用功能程序

    

猜你喜欢

转载自blog.csdn.net/u012351051/article/details/86701931