STM32
直播中

李丽华

7年用户 1424经验值
私信 关注
[问答]

实时时钟RTC闹钟的配置步骤有哪些呢

RTC是什么?

实时时钟RTC有何特性?
实时时钟RTC闹钟的配置步骤有哪些呢?

回帖(2)

陈明

2021-11-22 11:50:46
  RTC概述
  简介
  RTC (Real Time Clock):实时时钟
  STM32 的 RTC 外设,实质是一个掉电后还继续运行的定时器。RTC是个独立的BCD定时器/计数器。提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。
  两个32位寄存器包含二进码十进制格式(BCD)的秒,分钟,小时(12或24小时制),星期几,日期,月份和年份。此外,还可以提供二进制的亚秒值。系统可以自动将月份的天数补偿为28,29(闰年),30,31天。并且还可以进行夏令时补偿。
  主要特性
  包含亚秒、秒、分钟、小时(12/24 小时制)、星期几、日期、月份和年份的日历。
  软件可编程的夏令时补偿。
  两个具有中断功能的可编程闹钟。可通过任意日历字段的组合驱动闹钟。
  自动唤醒单元,可周期性地生成标志以触发自动唤醒中断。
  参考时钟检测:可使用更加精确的第二时钟源(50 Hz 或 60 Hz)来提高日历的精确度。
  利用亚秒级移位特性与外部时钟实现精确同步。
  可屏蔽中断/事件:
  — 闹钟 A
  — 闹钟 B
  — 唤醒中断
  — 时间戳
  — 入侵检测
  数字校准电路(周期性计数器调整)
  — 精度为 5 ppm
  — 精度为 0.95 ppm,在数秒钟的校准窗口中获得
  用于事件保存的时间戳功能(1 个事件)
  入侵检测:
  — 2 个带可配置过滤器和内部上拉的入侵事件
  20 个备份寄存器(80 字节)。发生入侵检测事件时,将复位备份寄存器。
  复用功能输出 (RTC_OUT),可选择以下两个输出之一:
  RTC_CALIB:512 Hz 或 1 Hz 时钟输出(LSE 频率为 32.768 kHz)。
  可通过将 RTC_CR 寄存器中的 COE[23] 位置 1 来使能此输出。该输出可连接到器件 RTC_AF1 功能。
  RTC_ALARM(闹钟 A、闹钟 B 或唤醒)。
  可通过配置 RTC_CR 寄存器的 OSEL[1:0] 位选择此输出。该输出可连接到器件
  RTC_AF1 功能。
  RTC 复用功能输入:
  RTC_TS:时间戳事件检测。该输入可连接到器件 RTC_AF1 和 RTC_AF2 功能。
  RTC_TAMP1:TAMPER1 事件检测。该输入可连接到器件 RTC_AF1 和RTC_AF2功能。
  RTC_TAMP2:TAMPER2 事件检测。
  RTC_REFIN:参考时钟输入(通常为市电,50 Hz 或 60 Hz)。
  
  RTC相关库函数
  RTC时钟源和时钟操作函数:
  void RCC_RTCCLKConfig(uint32_t CLKSource);//时钟源选择
  void RCC_RTCCLKCmd(FunctionalState NewState)//时钟使能
  RTC初始化函数
  ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct);
  typedef struct
  {
  uint32_t RTC_HourFormat; //小时格式:24/12
  uint32_t RTC_AsynchPrediv; //异步分频 系数
  uint32_t RTC_SynchPrediv; //同步分频系数
  }RTC_InitTypeDef
  RTC日历配置相关函数
  //设置时间
  ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
  //获取时间
  void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
  //设置日期
  ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
  //获取日期
  void RTC_GetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
  //获取到亚秒的信息
  uint32_t RTC_GetSubSecond(void);
  RTC闹钟相关函数
  //禁止或使能RTC闹钟。
  ErrorStatus RTC_AlarmCmd(uint32_t RTC_Alarm, FunctionalState NewState);
  //RTC闹钟时间配置。
  void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
  //获取RTC闹钟的时间配置
  void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
  //功能配置RTC AlarmA/B的亚秒
  void RTC_AlarmSubSecondConfig(uint32_t RTC_Alarm, uint32_t RTC_AlarmSubSecondValue, uint32_t RTC_AlarmSubSecondMask);
  //得到RTC的亚秒时间。
  uint32_t RTC_GetAlarmSubSecond(uint32_t RTC_Alarm);
  RTC周期唤醒相关函数
  //配置RTC唤醒时钟源
  void RTC_WakeUpClockConfig(uint32_t RTC_WakeUpClock);
  //配置RTC唤醒计数
  void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter);
  //得到唤醒定时器的计数值
  uint32_t RTC_GetWakeUpCounter(void);
  //关闭WAKE UP
  RTC_WakeUpCmd(DISABLE);
  RTC 中断配置以及状态相关函数
  //使能或禁止RTC中断
  void RTC_ITConfig(uint32_t RTC_IT, FunctionalState NewState);
  //查询RTC标志,主要用于非中断函数
  FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG);
  //清除RTC标志,主要用于非中断函数
  void RTC_ClearFlag(uint32_t RTC_FLAG);
  //查询RTC中断标志
  ITStatus RTC_GetITStatus(uint32_t RTC_IT);
  //清除RTC中断标志
  void RTC_ClearITPendingBit(uint32_t RTC_IT);
  RTC相关约束函数
  //取消写保护
  void RTC_WriteProtectionCmd(FunctionalState NewState);
  //进入配置模式,RTC_ISR_INITF位设置为1
  ErrorStatus RTC_EnterInitMode(void);
  //退出初始化模式。
  void RTC_ExitInitMode(void)
  其他相关函数
  //从备份数据寄存器读出数据。
  uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR);
  //写数据到RTC备份数据寄存器
  void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data);
  //使能或禁止RTC中断
  void RTC_ITConfig(uint32_t RTC_IT, FunctionalState NewState);
  RTC日历配置步骤
  使能PWR时钟:RCC_APB1PeriphClockCmd();
  使能后备寄存器访问: PWR_BackupAccessCmd();
  配置RTC时钟源,使能RTC时钟:
  RCC_RTCCLKConfig();
  RCC_RTCCLKCmd();
  如果使用LSE,要打开LSE:RCC_LSEConfig(RCC_LSE_ON);
  初始化RTC(同步/异步分频系数和时钟格式):RTC_Init ();
  设置时间:RTC_SetTime ();1
  设置日期:RTC_SetDate();2
  #define RTC_BKP_VALE 0x2021
  void Rtc_Init(void)
  {
  RTC_InitTypeDef RTC_InitStruct;
  RTC_TimeTypeDef RTC_TimeStruct;
  RTC_DateTypeDef RTC_DateStruct;
  //1、使能PWR时钟:
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
  //2、使能后备寄存器访问: 这类寄存器是掉电保存数据的
  PWR_BackupAccessCmd(ENABLE);
  if(RTC_ReadBackupRegister(RTC_BKP_DR0) != RTC_BKP_VALE)
  {
  //3、配置RTC时钟源,使能RTC时钟:
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  RCC_RTCCLKCmd(ENABLE);
  //要打开LSE:
  RCC_LSEConfig(RCC_LSE_ON);
  delay_ms(50); //延时等待时钟稳定
  RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24; //时间格式
  RTC_InitStruct.RTC_AsynchPrediv = 0x7F; //异步分频器
  RTC_InitStruct.RTC_SynchPrediv = 0xFF; //同步分频器
  //4、 初始化RTC(同步/异步分频系数和时钟格式):
  RTC_Init(&RTC_InitStruct);
  RTC_TimeStruct.RTC_H12 = RTC_H12_PM; //对于24小时格式,这个参数可以不用
  RTC_TimeStruct.RTC_Hours = 16; //时
  RTC_TimeStruct.RTC_Minutes = 36; //分
  RTC_TimeStruct.RTC_Seconds = 00; //秒
  //5、 设置时间:
  RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
  RTC_DateStruct.RTC_Year = 20; //20年,前年20要自己补
  RTC_DateStruct.RTC_Month = 8; //月
  RTC_DateStruct.RTC_Date = 19; //日
  RTC_DateStruct.RTC_WeekDay = 3; //星期
  //6、设置日期:
  RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
  //写后备寄存器
  RTC_WriteBackupRegister(RTC_BKP_DR0, RTC_BKP_VALE);
  }
  }
  RTC闹钟配置步骤
  所有 RTC 中断均与 EXTI 控制器相连。
  要使能 RTC 闹钟中断,需按照以下顺序操作:
  将 EXTI 线 17 配置为中断模式并将其使能,然后选择上升沿有效。
  配置 NVIC 中的 RTC_Alarm IRQ 通道并将其使能。
  配置 RTC 以生成 RTC 闹钟(闹钟 A 或闹钟 B)。
  ①:RTC已经初始化好相关参数。
  ②:关闭闹钟:RTC_AlarmCmd(RTC_Alarm_A,DISABLE);
  ③:配置闹钟参数:RTC_SetAlarm();3
  ④:开启闹钟:RTC_AlarmCmd(RTC_Alarm_A,EABLE);
  ⑤:开启配置闹钟中断:
  RTC_ITConfig();
  EXTI_Init();
  NVIC_Init();
  ⑥:编写中断服务函数:RTC_Alarm_IRQHandler();
  //闹钟A
  void RTC_Alarm_AInit(void)
  {
  RTC_TimeTypeDef RTC_AlarmTime;
  RTC_AlarmTypeDef RTC_AlarmStruct;
  EXTI_InitTypeDef EXTI_InitStruct;
  NVIC_InitTypeDef NVIC_InitStruct;
  //2、关闭闹钟:
  RTC_AlarmCmd(RTC_Alarm_A,DISABLE);
  //闹钟时间设置
  RTC_AlarmTime.RTC_H12 = RTC_H12_PM; //对于24小时格式,这个参数可以不用
  RTC_AlarmTime.RTC_Hours = 16; //时
  RTC_AlarmTime.RTC_Minutes = 36; //分
  RTC_AlarmTime.RTC_Seconds = 30; //秒
  RTC_AlarmStruct.RTC_AlarmTime = RTC_AlarmTime; //时间设置
  RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_None; //无掩码位 按实际时间来响应闹钟
  RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; //按星期来闹钟
  RTC_AlarmStruct.RTC_AlarmDateWeekDay = RTC_Weekday_Wednesday; //星期3
  //3、配置闹钟参数:
  RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStruct);
  //4、开启闹钟:
  RTC_AlarmCmd(RTC_Alarm_A,ENABLE);
  //5、开启配置闹钟中断:
  RTC_ITConfig(RTC_IT_ALRA,ENABLE);
  EXTI_InitStruct.EXTI_Line = EXTI_Line17; //中断线17
  EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
  EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Rising; //上升沿触发
  EXTI_InitStruct.EXTI_LineCmd= ENABLE; //中断线使能
  //初始化线上中断,设置触发条件等。
  EXTI_Init(&EXTI_InitStruct);
  NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn; //NVIC通道,在stm32f4xx.h可查看通道 (可变)
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; //响应优先级
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
  //配置中断分组(NVIC),并使能中断。
  NVIC_Init(&NVIC_InitStruct);
  }
  void RTC_Alarm_IRQHandler(void)
  {
  //判断中断标志是否为1
  if(EXTI_GetITStatus(EXTI_Line17) == SET)
  {
  //判断是否为闹钟A
  if(RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET)
  {
  //闹钟响应事件
  PFout(9) = 0;
  RTC_ClearFlag(RTC_FLAG_ALRAF);
  }
  //清空标志位
  EXTI_ClearITPendingBit(EXTI_Line17);
  }
  }
  //闹钟B
  void RTC_Alarm_BInit(void)
  {
  RTC_TimeTypeDef RTC_AlarmTime;
  RTC_AlarmTypeDef RTC_AlarmStruct;
  EXTI_InitTypeDef EXTI_InitStruct;
  NVIC_InitTypeDef NVIC_InitStruct;
  //2、关闭闹钟:
  RTC_AlarmCmd(RTC_Alarm_B,DISABLE);
  //闹钟时间设置
  RTC_AlarmTime.RTC_H12 = RTC_H12_PM; //对于24小时格式,这个参数可以不用
  RTC_AlarmTime.RTC_Hours = 16; //时
  RTC_AlarmTime.RTC_Minutes = 36; //分
  RTC_AlarmTime.RTC_Seconds = 35; //秒
  RTC_AlarmStruct.RTC_AlarmTime = RTC_AlarmTime; //时间设置
  RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_None; //无掩码位 按实际时间来响应闹钟
  RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date; //按日期来闹钟
  RTC_AlarmStruct.RTC_AlarmDateWeekDay = 19; //19日
  //3、配置闹钟参数:
  RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_B, &RTC_AlarmStruct);
  //4、开启闹钟:
  RTC_AlarmCmd(RTC_Alarm_B,ENABLE);
  //5、开启配置闹钟中断:
  RTC_ITConfig(RTC_IT_ALRB,ENABLE);
  EXTI_InitStruct.EXTI_Line = EXTI_Line17; //中断线17
  EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
  EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Rising; //上升沿触发
  EXTI_InitStruct.EXTI_LineCmd= ENABLE; //中断线使能
  //初始化线上中断,设置触发条件等。
  EXTI_Init(&EXTI_InitStruct);
  NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn; //NVIC通道,在stm32f4xx.h可查看通道 (可变)
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; //响应优先级
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
  //配置中断分组(NVIC),并使能中断。
  NVIC_Init(&NVIC_InitStruct);
  }
  
举报

蒋喜玲

2021-11-22 11:50:55
main.c
  int main(void)
  {
  RTC_TimeTypeDef RTC_TimeStruct;
  RTC_DateTypeDef RTC_DateStruct;
  //NVIC分组(一个工程当中只能配置一次分组)抢占优先级2位,值范围:0~3;响应优先级2位,值范围:0~3;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  Delay_Init();
  Led_Init();
  Usart1_Init();
  Rtc_Init();
  RTC_Alarm_AInit();
  while(1)
  {
  RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
  RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
  printf(“时间:%d:%d:%drn”, RTC_TimeStruct.RTC_Hours, RTC_TimeStruct.RTC_Minutes,
  RTC_TimeStruct.RTC_Seconds);
  printf(“日期:20%d年%d月%d日,星期%drnrn”,RTC_DateStruct.RTC_Year,
  RTC_DateStruct.RTC_Month, RTC_DateStruct.RTC_Date, RTC_DateStruct.RTC_WeekDay);
  delay_s(1);
  }
  return 0;
  }
  RTC周期性自动唤醒配置一般步骤
  RTC已经初始化好相关参数。
  关闭WakeUp:RTC_WakeUpCmd(DISABLE);
  配置WakeUp时钟分频系数/来源: RTC_WakeUpClockConfig();
  设置WakeUp自动装载寄存器:RTC_SetWakeUpCounter();
  使能WakeUp : RTC_WakeUpCmd( ENABLE);
  开启配置闹钟中断:
  RTC_ITConfig();
  EXTI_Init();
  NVIC_Init();
  编写中断服务函数: RTC_WKUP_IRQHandler();
  ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
  函数功能:时间设置
  uint32_t RTC_Format:存储格式
  RTC_Format_BIN:二进制存储
  RTC_Format_BCD:BCD码格式
  typedef struct
  {
  uint8_t RTC_Hours; //时
  uint8_t RTC_Minutes; //分
  uint8_t RTC_Seconds; //秒
  uint8_t RTC_H12; //上下午
  }RTC_TimeTypeDef;
  ↩︎
  ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct)
  函数功能:日期设置
  uint32_t RTC_Format:存储格式
  RTC_Format_BIN:二进制存储
  typedef struct
  {
  uint8_t RTC_WeekDay; //星期
  uint8_t RTC_Month; //月
  uint8_t RTC_Date; //日
  uint8_t RTC_Year; //年
  }RTC_DateTypeDef;
  ↩︎
  void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
  函数功能:设置闹钟
  uint32_t RTC_Format:存储格式
  RTC_Format_BIN:二进制存储
  RTC_Format_BCD:BCD码格式
  uint32_t RTC_Alarm:选择哪个闹钟
  typedef struct
  {
  RTC_TimeTypeDef RTC_AlarmTime; //时间设置结构体
  uint32_t RTC_AlarmMask; //掩码位
  uint32_t RTC_AlarmDateWeekDaySel; //选择闹钟响应方式(日期,星期)
  uint8_t RTC_AlarmDateWeekDay; //日期或者星期的设置
  }RTC_AlarmTypeDef;
  typedef struct
  {
  uint8_t RTC_Hours; //时
  uint8_t RTC_Minutes; //分
  uint8_t RTC_Seconds; //秒
  uint8_t RTC_H12; //上下午
  }RTC_TimeTypeDef; ↩︎
举报

更多回帖

发帖
×
20
完善资料,
赚取积分