RTC实时时钟
一、简介
RTC是一个独立的BCD格式定时器,提供一个时钟日历,两个可编程报警中断,一个具有中断功能周期性可编程唤醒标志,RTC和时钟配置系统处于后备区域。
通过两个32位寄存器以BCD格式实现秒、分钟、小时(12、24小时制),日(星期)、月和年等信息。只要有电(VBAT提供),RTC就永不停止。RTC时钟源RTCCLK可从LSE、LSI和Divided HSE三者中选择,通常情况下使用LSE。
32768
=
2
15
32768 = 2^{15}
32768=215,经过15位分频器的自然溢出即可得到1Hz的频率,15位的计数器从0开始计数,计到最大值32767自然溢出,这个溢出信号就是1Hz信号。
RTCCLK先进行平滑校准,然后进行非同步预分频,最后进行同步预分频得到1Hz。相关频率计算公式如下:
f
C
K
−
A
P
R
E
=
f
R
T
C
C
L
K
P
R
E
D
I
V
−
A
+
1
f_{CK - APRE}=\frac {f_{RTCCLK}}{PREDIV-A + 1}
fCK−APRE=PREDIV−A+1fRTCCLK,
f
C
K
−
A
P
R
E
f_{CK - APRE}
fCK−APRE是用于为二进制
R
T
C
−
S
S
R
RTC-SSR
RTC−SSR子秒下计数器计时,减到0,
R
T
C
−
S
S
R
RTC-SSR
RTC−SSR会重新加载
P
R
E
D
I
V
−
S
PREDIV-S
PREDIV−S的内容。
f
C
K
−
S
P
R
E
=
f
C
K
−
A
P
R
E
P
R
E
D
I
V
−
S
+
1
f_{CK - SPRE}=\frac {f_{CK-APRE}}{PREDIV-S + 1}
fCK−SPRE=PREDIV−S+1fCK−APRE,
f
C
K
−
S
P
R
E
f_{CK - SPRE}
fCK−SPRE可用于更新日历或者作为16位唤醒自动重载定时器的时基单元。RTC基本结构如下
RTC初始化与配置
- 使能PWR和BKP时钟
- 设置PWR_CR的DBP位,使能对BKP和RTC的访问
- 对RTC寄存器的写操作都必须在前一次写操作结束后进行
RTC外设与BKP(备份寄存器)和PWR(电源)有关,这里一起讲解。
二、Unix时间戳
Unix事件戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不用考虑闰秒。时间戳存储在一个秒计数器中,是32位/64位的整型变量,不同时区通过添加偏移来得到当地时间。由于地球自转一周时间不固定,GMT对时间的定义更标准,为消除计时一天和地球自转一周的误差,通过执行闰秒
来保证计时一天的时间与地球自转一周的时间协调一致。
- UTC(Universal Time Coordinated)协调世界时是一种以原子钟为基础的时间计量系统。
- GMT(Greenwich Mean Time)格林尼治标准时间是一种以地球自转为基础的时间计量系统。
时间戳转换,C语言的time.h
模块提供了时间获取和时间戳转换的相关函数。可以方便地进行秒计数器、日期时间和字符串之间的转换。
上面几个函数之间关系如下
相应的实例代码如下
#include <stdio.h>
#include <time.h>
/*验证时间戳功能*/
time_t time_cnt; //默认情况下是64位有符号秒计数器类型
struct tm time_date; //tm结构体包含事件表示的元素,其中年份是从1900开始计算
char *time_str; //指向一个表示时间的字符串
/*time_t time(time_t *)函数获取系统时钟,不能用于离线裸机系统*/
time_t Get_timestamp()
{
return time(NULL);
}
/*struct tm* gmtime(const time_t*)函数将秒计数器转换为日期时间GMT格式*/
struct tm* Get_timeGMT(time_t* timestamp)
{
return gmtime(timestamp);
}
/*struct tm* localtime(const time_t*)函数将秒计数器转换为当地日期时间,自动判断时区*/
struct tm* Get_localtime(time_t* timestamp)
{
return localtime(timestamp);
}
/*time_t mktime(struct tm*)函数将当地日期时间转换为秒计数器*/
time_t localtime_stamp(struct tm* localtime)
{
return mktime(localtime);
}
/*char* ctime(const time_t*)函数将秒计数器转换为字符串*/
char* timetostr(time_t* timestamp)
{
return ctime(timestamp);
}
int main()
{
time_cnt = Get_timestamp();
printf("Time_cnt = %d\n", time_cnt);
time_date = *Get_timeGMT(&time_cnt);
printf("\n");
printf("Time: %d-%d-%d %d:%d:%d\n", time_date.tm_year + 1900, time_date.tm_mon + 1, time_date.tm_mday, time_date.tm_hour, time_date.tm_min, time_date.tm_sec);
printf("\n");
time_date = *Get_localtime(&time_cnt);
printf("localTime: %d-%d-%d %d:%d:%d\n", time_date.tm_year, time_date.tm_mon, time_date.tm_mday, time_date.tm_hour, time_date.tm_min, time_date.tm_sec);
printf("\n");
printf("localTime_stamp: %d\n", localtime_stamp(&time_date));
printf("\n");
printf("%s\n", timetostr(&time_cnt));
return 0;
}
三、BKP
BKP(Backup Register)备份寄存器,可用于存储用户应用程序数据。VDD断开后,由VBAT维持供电,只要有电数据就不会丢失。通过备份域复位执行复位,由篡改/入侵检测(tamper detection)事件触发,一个篡改检测事件复位所有备份寄存器(防止外部窃取数据)。STM32F4xxBKP拥有20个32位寄存器,存储80字节用户应用数据。这里给出BKP基本结构