STM32——实时时钟RTC的日历读取

文章目录

  • 实验环境
  • 一、RTC 实时时钟简介
  • 二、RTC 外设框图剖析
  • 三、CubeMX配置RTC
  • 四、KEIL代码修改
  • 五、实验结果
  • 六、验证初始时间
  • 七、总结


实验环境

软件:
STM32CubeMX
KEIL5
mcuisp
串口通信助手
硬件:
STM32F103C8Tx
杜邦线,面包板,USB转TTL

一、RTC 实时时钟简介

  • STM32的 RTC 外设(Real Time Clock),实质是一个掉电后还继续运行的定时器。从定时器的角度来说,相对于通用定时器 TIM 外设,它十分简单,只有很纯粹的计时和触发中断的功能;但从掉电还继续运行的角度来说,它却是 STM32 中唯一一个具有如此强大功能的外设。所以 RTC 外设的复杂之处并不在于它的定时功能,而在于它掉电还继续运行的特性。
  • STM32的 RTC 外设(Real Time Clock),实质是一个掉电后还继续运行的定时器。从定时器的角度来说,相对于通用定时器 TIM 外设,它十分简单,只有很纯粹的计时和触发中断的功能;但从掉电还继续运行的角度来说,它却是 STM32 中唯一一个具有如此强大功能的外设。所以 RTC 外设的复杂之处并不在于它的定时功能,而在于它掉电还继续运行的特性。

二、RTC 外设框图剖析

STM32——实时时钟RTC的日历读取_第1张图片

框图中浅灰色的部分都是属于备份域的,在VDD掉电时可在VBAT的驱动下继续运行。这部分仅包括 RTC 的分频器,计数器,和闹钟控制器。若 VDD 电源有效,RTC 可以触发RTC_Second(秒中断)RTC_Overflow(溢出事件)和 RTC_Alarm(闹钟中断)。从结构图可以分析到,其中的定时器溢出事件无法被配置为中断。若 STM32 原本处于待机状态,可由闹钟事件或 WKUP 事件(外部唤醒事件,属于 EXTI 模块,不属于 RTC)使它退出待机模式。闹钟事件是在计数器 RTC_CNT 的值等于闹钟寄存器 RTC_ALR 的值时触发的。

在备份域中所有寄存器都是 16 位的, RTC 控制相关的寄存器也不例外。它的计数器RTC_CNT 的 32 位由 RTC_CNTL 和 RTC_CNTH 两个寄存器组成,分别保存定时计数值的低 16 位和高 16 位。在配置 RTC 模块的时钟时,通常把输入的 32768Hz 的 RTCCLK 进行32768分频得到实际驱动计数器的时钟TR_CLK = RTCCLK/32768= 1 Hz,计时周期为1秒,计时器在 TR_CLK 的驱动下计数,即每秒计数器 RTC_CNT 的值加 1。

三、CubeMX配置RTC

1.配置RCC
设置高速外部时钟HSE 选择外部时钟源
使能外部晶振LSE

RTC设备因为其独特的运行方式(即掉电依旧运行)使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,资源消耗太大,小小的纽扣电池根本吃不消。没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE

STM32——实时时钟RTC的日历读取_第2张图片

2.配置RTC
STM32——实时时钟RTC的日历读取_第3张图片

  • Activate Clock Source 激活时钟源
  • Activate calendar激活日历

这两个都要点,作用也很明显,先是使能时钟源,再使能RTC日历

  • RTC_OUT: Not RTC_OUT
  • Tamper: ×

第一个是是否使能 tamper(PC13)引脚上输出校正的秒脉冲时钟,
第二个: RTC入侵检测校验功能

下面配置初始时间
STM32——实时时钟RTC的日历读取_第4张图片
此处设置时间为2022/11/2 14:48:00

  • Data Format: 日期格式
  • Binary data format 十六进制
  • BCD data format BCD码进制

使用自动配置,初始化时间必须使用BCD data format,原因是库函数存在bug,如果使用Binary data format,月份配置会出错,比如说11月,配置时会赋值为RTC_MONTH_NOVEMBER,而此宏定义值为0x11,也就是说其十进制值为17

3 .使能串口
STM32——实时时钟RTC的日历读取_第5张图片

4.时钟源设置

STM32——实时时钟RTC的日历读取_第6张图片

- 1.设置RTC时钟为LSE
- 2.选择外部时钟HSE 8MHZ,PLL锁相环倍频9倍
- 3.系统时钟来源选择为PLL
- 4.置APB1分频器为 /2

5.项目文件设置
STM32——实时时钟RTC的日历读取_第7张图片
STM32——实时时钟RTC的日历读取_第8张图片
这样项目就创建完成了

四、KEIL代码修改

打开stm32f1xx_hal_rtc.h文件可以看到以下函数

/* RTC Time and Date functions ************************************************/
/** @addtogroup RTC_Exported_Functions_Group2
  * @{
  */
HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);/*设置系统时间*/
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);/*读取系统时间*/
HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format);/*设置系统日期*/
HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format);/*读取系统日期*/
/**
  * @}
  */

/* RTC Alarm functions ********************************************************/
/** @addtogroup RTC_Exported_Functions_Group3
  * @{
  */
HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format);/*启动报警功能*/
HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format);/*设置报警中断*/
HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm);/*报警时间回调函数*/
HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format);
void              HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc);
HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout);
void              HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc);

/*时间结构体*/
typedef struct
{
  uint8_t Hours;            /*!< Specifies the RTC Time Hour.
                                 This parameter must be a number between Min_Data = 0 and Max_Data = 23 */

  uint8_t Minutes;          /*!< Specifies the RTC Time Minutes.
                                 This parameter must be a number between Min_Data = 0 and Max_Data = 59 */

  uint8_t Seconds;          /*!< Specifies the RTC Time Seconds.
                                 This parameter must be a number between Min_Data = 0 and Max_Data = 59 */

} RTC_TimeTypeDef;

/*日期结构体*/
typedef struct
{
  uint8_t WeekDay;  /*!< Specifies the RTC Date WeekDay (not necessary for HAL_RTC_SetDate).
                         This parameter can be a value of @ref RTC_WeekDay_Definitions */

  uint8_t Month;    /*!< Specifies the RTC Date Month (in BCD format).
                         This parameter can be a value of @ref RTC_Month_Date_Definitions */

  uint8_t Date;     /*!< Specifies the RTC Date.
                         This parameter must be a number between Min_Data = 1 and Max_Data = 31 */

  uint8_t Year;     /*!< Specifies the RTC Date Year.
                         This parameter must be a number between Min_Data = 0 and Max_Data = 99 */

} RTC_DateTypeDef;

在main.c文件中重写fputc函数,完成printf函数的重定向

//添加头文件#include "stdio.h"
int fputc(int ch,FILE *f){
 uint8_t temp[1]={ch};
 HAL_UART_Transmit(&huart1,temp,1,2);
 return ch;
}

在main.c中定义时间和日期的结构体用来获取时间和日期

RTC_DateTypeDef Date;  //获取日期结构体
RTC_TimeTypeDef	Time;   //获取时间结构体

在main函数的while循环中添加以下代码

		//获取RTC时间
	  HAL_RTC_GetTime(&hrtc, &Time, RTC_FORMAT_BIN);
      //获取RTC日期
      HAL_RTC_GetDate(&hrtc, &Date, RTC_FORMAT_BIN);

      //日期展示格式:年/月/日
      printf("%02d/%02d/%02d\r\n",2000 + Date.Year, Date.Month, Date.Date);
     //时间展示格式:时:分:秒
      printf("%02d:%02d:%02d\r\n",Time.Hours, Time.Minutes, Time.Seconds);

      printf("\r\n");

      HAL_Delay(1000);

添加星期

	switch(Date.WeekDay)
			{
				case 1:printf("星期一\r\n");break;
				case 2:printf("星期二\r\n");break;
				case 3:printf("星期三\r\n");break;
				case 4:printf("星期四\r\n");break;
				case 5:printf("星期五\r\n");break;
				case 6:printf("星期六\r\n");break;
				case 7:printf("星期七\r\n");
			}

五、实验结果

STM32——实时时钟RTC的日历读取_第9张图片

六、验证初始时间

HAL库配置RTC时可以看到RTC默认初始时间是0年1月1日零时零分零秒
STM32——实时时钟RTC的日历读取_第10张图片
先将上面代码初始日期时间清零,查看星期数,由于RTC可以自动生成正确的星期数,将输出的星期数与1970年1月1日比较,就可以知道RTC初始时间是否是1970年1月1号

		Time.Hours=0,Time.Minutes=0,Time.Seconds=0;//时间清零
		Date.Year=0,Date.Month=1,Date.Date=1;//日期清零
		HAL_RTC_SetTime(&hrtc,&Time,RTC_FORMAT_BCD);
		HAL_RTC_SetDate(&hrtc,&Date,RTC_FORMAT_BCD);
		while(1)
		{
	 /* Get the RTC current Time */
	    HAL_RTC_GetTime(&hrtc, &Time, RTC_FORMAT_BIN);
      /* Get the RTC current Date */
      HAL_RTC_GetDate(&hrtc, &Date, RTC_FORMAT_BIN);

      /* Display date Format : yy/mm/dd */
      printf("%02d/%02d/%02d\r\n",Date.Year, Date.Month, Date.Date);
}
   

查看结果:
STM32——实时时钟RTC的日历读取_第11张图片
已知1970年1月1日为星期4,所以RTC开始日期不是1970年1月1日。

七、总结

使用CubeMX会使大部分底层原理没有接触到,想要更加深入了解RTC底层构造需要查看官方文档进行进一步学习。

你可能感兴趣的:(stm32,单片机,实时音视频)