打印
[应用相关]

RTC自动唤醒机制

[复制链接]
3884|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
磨砂|  楼主 | 2019-6-13 19:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
超低功耗产品必然涉及到“唤醒”机制,唤醒后执行 正常的功能代码,这个“唤醒”动作有多种,基本上有外部中断、中断事件、RTC自动唤醒等,外部中断多是IO口中断,比如按键触发,而RTC自动中断相比较“智能”一些,倒计时一定时间后,自动唤醒CPU,所以RTC自动唤醒基本上就是 为超低功耗定制 的,用起来非常方便,先看下STM32L151的RTC系统时钟树:



使用特权

评论回复
沙发
磨砂|  楼主 | 2019-6-13 19:14 | 只看该作者
上图中的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 计数器事件。


使用特权

评论回复
板凳
磨砂|  楼主 | 2019-6-13 19:15 | 只看该作者
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);

}


使用特权

评论回复
地板
磨砂|  楼主 | 2019-6-13 19:15 | 只看该作者
基本流程为:

   ① 使能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 中断


使用特权

评论回复
5
磨砂|  楼主 | 2019-6-13 19:16 | 只看该作者
进行初始化这些后,还需要编写wakeup  中断服务函数:



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


使用特权

评论回复
6
磨砂|  楼主 | 2019-6-13 19:16 | 只看该作者
重点就是要清除WUT和EXTI_Line20中断标志。

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



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

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

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


使用特权

评论回复
7
dongnanxibei| | 2019-6-14 00:21 | 只看该作者
RTC的重要性。

使用特权

评论回复
8
磨砂|  楼主 | 2019-6-17 09:57 | 只看该作者

是的 确实很重要 但是明白的人并不是很多

使用特权

评论回复
9
keaibukelian| | 2019-7-5 10:34 | 只看该作者
通过什么进行唤醒啊

使用特权

评论回复
10
labasi| | 2019-7-5 11:03 | 只看该作者
好像是外部中断唤醒的

使用特权

评论回复
11
renzheshengui| | 2019-7-5 11:25 | 只看该作者
主要看寄存器的设置

使用特权

评论回复
12
712abc| | 2020-8-11 11:31 | 只看该作者
这个休眠时钟计算准确吗?不知道用内部时钟和外部晶振的时间误差有多大

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

4126

帖子

2

粉丝