1087|9

215

帖子

0

资源

一粒金砂(高级)

【雅特力开发板 AT32F421 测评】2 . 外设ERTC的使用 [复制链接]

首先来介绍一下这个外设:

      实时时钟 (ERTC) 是一个独立的 BCD 定时器/计数器。 ERTC 提供一个日历时钟、一个可编程闹钟中断。
两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或 24 小时制)、星期几、日期、
月份和年份。此外,还可提供二进制格式的亚秒值。
系统可以自动将月份的天数补偿为 28、 29(闰年)、 30 和 31 天。并且还可以进行夏令时补偿。
其它 32 位寄存器还包含可编程的闹钟亚秒、秒、分钟、小时、星期几和日期。
此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。
上电复位后,所有 ERTC 寄存器都会受到保护,以防止可能的非正常写访问。
无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内, ERTC
便不会停止工作。

2. 它的特性如下:

ERTC的主要特性
● 包含亚秒、秒、分钟、小时( 12/24 小时制)、星期几、日期、月份和年份的日历。
● 软件可编程的夏令时补偿。
● 一个具有中断功能的可编程闹钟。可通过任意日历字段的组合驱动闹钟。
● 参考时钟检测:可使用更加精确的第二时钟源( 50 Hz 或 60 Hz)来提高日历的精确
度。
● 利用亚秒级移位特性与外部时钟实现精确同步。
● 可屏蔽中断/事件:
 闹钟 A
 时间戳
 入侵检测
● 数字校准电路(周期性计数器调整 )
 精度为 0.95 ppm,在数秒钟的校准窗口中获得
● 用于事件保存的时间戳功能( 1 个事件)
● 入侵检测:
 1个带可配置过滤器和内部上拉的入侵事件
● 5 个备份寄存器( 20 字节 )。发生入侵检测事件时,将复位备份寄存器。
● 复用功能输出 (ERTC_OUT),可选择以下两个输出之一:
 ERTC_CAL: 512 Hz 或 1 Hz 时钟输出( LSE 频率为 32.768 kHz)。可通过将
ERTC_CTRL 寄存器中的 CALOE[23] 位置 1 来使能此输出。该输出可连接到器
件 ERTC_AF1 功能。
 ERTC_ALARM(闹钟 A)。 可通过配置 ERTC_CTRL 寄存器的 OSEL[1:0] 位
选择此输出。该输出可连接到器件 ERTC_AF1 功能。
● ERTC 复用功能输入:
 ERTC_TS:时间戳事件检测。该输入可连接到器件 ERTC_AF1。
 ERTC_TAMP: TAMPER 事件检测。该输入可连接到器件 ERTC_AF1。
 ERTC_REFIN:参考时钟输入(通常为市电, 50 Hz 或 60 Hz)。
3. 

官方给说明如下:

As an application example, it demonstrates how to setup the ERTC peripheral, in 
terms of prescaler and interrupts, to be used to keep time and to generate 
alarm interrupt. 

One from the following clock can be used as ERTC clock source (uncomment the
corresponding define in main.c): 
  - LSE oscillator clock usually delivered by a 32.768 kHz quartz.
  - LSI oscillator clock
  
The ERTC is in the backup (BKP) domain, still powered by VBAT when VDD is switched off,
so the ERTC configuration is not lost if a battery is connected to the VBAT pin. 
A key value is written in backup data register 0 to indicate if the ERTC is already
configured.

首先,我们要初始化这个外设:

/**
  * @brief Configure the ERTC peripheral by selecting the clock source.
  * @param  None
  * @retval None
  */
static void ERTC_Config(void)
{
  ERTC_DateType ERTC_DateStructure;
  
  /* Enable the PWR clock */
  RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR, ENABLE);

  /* Allow access to ERTC */
  PWR_BackupAccessCtrl(ENABLE);
   
  /* Reset ERTC Domain */
  RCC_BackupResetCmd(ENABLE);
  RCC_BackupResetCmd(DISABLE);
  
#if defined (ERTC_CLOCK_SOURCE_LSI)  /* LSI used as ERTC source clock*/
  /* The ERTC Clock may varies due to LSI frequency dispersion */   
  /* Enable the LSI OSC */ 
  RCC_LSICmd(ENABLE);

  /* Wait till LSI is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSISTBL) == RESET)
  {
  }

  /* Select the ERTC Clock Source */
  RCC_ERTCCLKConfig(RCC_ERTCCLKSelection_LSI);
  
  /* ck_spre(1Hz) = ERTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
  uwSynchPrediv = 0xFF;
  uwAsynchPrediv = 0x7F;

#elif defined (ERTC_CLOCK_SOURCE_LSE) /* LSE used as ERTC source clock */
  /* Enable the LSE OSC */
  RCC_LSEConfig(RCC_LSE_ENABLE);

  /* Wait till LSE is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSESTBL) == RESET)
  {
  }

  /* Select the ERTC Clock Source */
  RCC_ERTCCLKConfig(RCC_ERTCCLKSelection_LSE);
  /* ck_spre(1Hz) = ERTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
  uwSynchPrediv = 0xFF;
  uwAsynchPrediv = 0x7F;
#endif /* ERTC_CLOCK_SOURCE_LSI */
  
  /* Enable the ERTC Clock */
  RCC_ERTCCLKCmd(ENABLE);  
  
  /* Wait for ERTC APB registers synchronisation */
  ERTC_WaitForSynchro();
  
  /* Configure the ERTC data register and ERTC prescaler */
  ERTC_InitStructure.ERTC_AsynchPrediv = uwAsynchPrediv;
  ERTC_InitStructure.ERTC_SynchPrediv = uwSynchPrediv;
  ERTC_InitStructure.ERTC_HourFormat = ERTC_HourFormat_24;
  ERTC_Init(&ERTC_InitStructure);
  
  /* Set the alarm 05h:20min:10s */
  ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_AMPM    = ERTC_H12_AM;
  ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Hours   = 5;
  ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Minutes = 20;
  ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Seconds = 10;
  ERTC_AlarmStructure.ERTC_AlarmDateWeek = 11;
  ERTC_AlarmStructure.ERTC_AlarmDateWeekSel = ERTC_AlarmDateWeekSel_Date;
  ERTC_AlarmStructure.ERTC_AlarmMask = ERTC_AlarmMask_DateWeek;
  
  /* Configure the ERTC Alarm A register */
  ERTC_SetAlarmValue(ERTC_Format_BIN, ERTC_AlA, &ERTC_AlarmStructure);
  
  /* Enable ERTC Alarm A Interrupt */
  ERTC_INTConfig(ERTC_INT_ALA, ENABLE);
  
  /* Enable the alarm */
  ERTC_AlarmCmd(ERTC_AlA, ENABLE);
  
  ERTC_ClearFlag(ERTC_FLAG_ALAF);
  
  /* Set the date: Friday January 11th 2013 */
  ERTC_DateStructure.ERTC_Year    = 21;
  ERTC_DateStructure.ERTC_Month   = 4;
  ERTC_DateStructure.ERTC_Date    = 9;
  ERTC_DateStructure.ERTC_WeekDay = 5;
  ERTC_SetDateValue(ERTC_Format_BIN, &ERTC_DateStructure);
  
  /* Set the time to 05h 20mn 00s AM */
  ERTC_TimeStructure.ERTC_AMPM    = ERTC_H12_AM;
  ERTC_TimeStructure.ERTC_Hours   = 5;
  ERTC_TimeStructure.ERTC_Minutes = 20;
  ERTC_TimeStructure.ERTC_Seconds = 0; 
  
  ERTC_SetTimeValue(ERTC_Format_BIN, &ERTC_TimeStructure);   
  
  /* Indicator for the ERTC configuration */
  ERTC_WriteBackupRegister(ERTC_BKP_DT0, 0x32F1);
}

然后,每次上电后,就会判断备份寄存器中是否已经配置好时间,不需要每次上电后都进行配置:

我们的主函数如下:

int main(void)
{
  NVIC_InitType  NVIC_InitStructure;
  EXTI_InitType  EXTI_InitStructure;
  int temp=0;
  /* AT Board Initial */
  AT32_Board_Init();
  
  /* initialize UART1  */
  UART_Print_Init(115200);
  
  if (ERTC_ReadBackupRegister(ERTC_BKP_DT0) != 0x32F1)
  {  
    /* ERTC configuration  */
    ERTC_Config();
  }
  else
  {
    /* Check if the Power On Reset flag is set */
    if (RCC_GetFlagStatus(RCC_FLAG_PORST) != RESET)
    {
      /* Power On Reset occurred     */
      AT32_LEDn_ON(LED3);
    }
    /* Check if the Pin Reset flag is set */
    else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
    {
      /* External Reset occurred */
      AT32_LEDn_ON(LED4);
    }
    
    /* Enable the PWR clock */
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR, ENABLE);

    /* Allow access to ERTC */
    PWR_BackupAccessCtrl(ENABLE);

    /* Wait for ERTC APB registers synchronisation */
    ERTC_WaitForSynchro();

    /* Clear the ERTC Alarm Flag */
    ERTC_ClearFlag(ERTC_FLAG_ALAF);

    /* Clear the EXTI Line 17 Pending bit (Connected internally to ERTC Alarm) */
    EXTI_ClearIntPendingBit(EXTI_Line17);
  }
   
  /* ERTC Alarm A Interrupt Configuration */
  /* EXTI configuration *******************************************************/
  EXTI_ClearIntPendingBit(EXTI_Line17);
  EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineEnable = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
  
  /* Enable the ERTC Alarm Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = ERTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  while (1)
  {
    ERTC_GetTimeValue(ERTC_Format_BIN, &ERTC_TimeStructure);  
    ERTC_GetDateValue(ERTC_Format_BIN, &ERTC_DateStructure);
          
    if(temp != ERTC_TimeStructure.ERTC_Seconds)
    {
      temp = ERTC_TimeStructure.ERTC_Seconds;
      /* Display time Format : hh:mm:ss */
      printf("20%02d-%02d-%02d ", ERTC_DateStructure.ERTC_Year, ERTC_DateStructure.ERTC_Month, ERTC_DateStructure.ERTC_Date);       
      printf("%0.2d:%0.2d:%0.2d ", ERTC_TimeStructure.ERTC_Hours, ERTC_TimeStructure.ERTC_Minutes, ERTC_TimeStructure.ERTC_Seconds);
      printf("week %d\r\n", ERTC_DateStructure.ERTC_WeekDay);      
      
    }
  }
}

到此,我们的代码就写好了:

来,看看效果吧~

QQ浏览器截图20210409192753.png

这个增强型RTC带有硬件日历的哦,比如,2月运行到了28号,会直接跳到3月1号,自动判断闰年。所以使用起来会方便很多呢。

最后附上工程源码。欢迎下载点评~

ERTC_Calendar_V1.0.0.zip (981.22 KB, 下载次数: 4)

赞赏

1

查看全部赞赏

个人签名

gitee/casy


回复

2021

帖子

3

资源

版主

感谢分享,期待后续测评!


回复

6748

帖子

0

资源

五彩晶圆(初级)

谢谢分享

能自动判断闰年这个应该是ERTC内固定 提供日历时钟吧

点评

是的,寄存器我还要升入进去才能领略其中的奥秘呢  详情 回复 发表于 2021-4-12 19:59

回复

215

帖子

0

资源

一粒金砂(高级)

Jacktang 发表于 2021-4-11 08:41 谢谢分享 能自动判断闰年这个应该是ERTC内固定 提供日历时钟吧

是的,寄存器我还要升入进去才能领略其中的奥秘呢

个人签名

gitee/casy


回复

5259

帖子

18

资源

五彩晶圆(中级)

入侵检测是个什么功能。。。?

个人签名

默认摸鱼


回复

76

帖子

2

资源

一粒金砂(中级)

亚秒级的延时却是很强,可以省一个定时器了。


回复

3926

帖子

1

资源

版主

增强型RTC带有硬件日历的哦 不错

回复

2

帖子

0

资源

一粒金砂(初级)

你好  最近在用这个芯片做 STOP 模式下  ,用ERTC的Alarm 来作为唤醒,来退出STOP模式,但是每次的唤醒时间都是1秒,而且找不到如何配置成大于1秒的方法,楼主有办法吗?


回复

2

帖子

0

资源

一粒金砂(初级)

ERTC 在STOP后  第一个中断产生后 好像需要再重新配置LSE的使能和ERTC的使能,不然不能再产生ERTC的Alarm中断


回复

1151

帖子

3

资源

版主

我使用的AT32F45也跟你的一样,感觉ERTC使用起来还是很方便的。


回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表