1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > STM32——实时时钟RTC的日历读取

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

时间:2021-12-26 07:24:35

相关推荐

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 外设框图剖析

框图中浅灰色的部分都是属于备份域的,在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

2.配置RTC

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

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

RTC_OUT: Not RTC_OUTTamper: ×

第一个是是否使能 tamper(PC13)引脚上输出校正的秒脉冲时钟,

第二个: RTC入侵检测校验功能

下面配置初始时间

此处设置时间为/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 .使能串口

4.时钟源设置

- 1.设置RTC时钟为LSE

- 2.选择外部时钟HSE 8MHZ,PLL锁相环倍频9倍

- 3.系统时钟来源选择为PLL

- 4.置APB1分频器为 /2

5.项目文件设置

这样项目就创建完成了

四、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_TimeTypeDefTime; //获取时间结构体

在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");}

五、实验结果

六、验证初始时间

HAL库配置RTC时可以看到RTC默认初始时间是0年1月1日零时零分零秒

先将上面代码初始日期时间清零,查看星期数,由于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);}

查看结果:

已知1970年1月1日为星期4,所以RTC开始日期不是1970年1月1日。

七、总结

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。