Unix时间戳
最早是在Unix系统使用的,之后很多由Unix演变而来的系统也都继承了Unix时间戳的规定。目前,Linux、Windows、安卓这些系统,其底层的计时系统都是使用Unix时间戳。
Uinx时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒。也就是说时间戳是一个秒计数器,且只记秒,不会向分钟、小时进位。
其年月日小时分钟均通过计算秒得出。
世界上所有时区共用一个时间戳的秒计数器,不同时区通过添加偏移来得到当地时间。如上图所示,相比于伦敦,北京时间偏移了8个小时。
UTC/GMT
GMT即格林尼治标准时间,可理解为伦敦时间,是一种以地球自转为基础的时间计量系统。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准。
但GMT是以前的时间标准,因为地球自转一周的时间是不固定的,由于潮汐力、地球活动等原因,地球目前是越转越慢的,因此时间基准也是不固定的(即1秒到底是多长)。
为了时间的定义更标准,科学家又提出来新的计时系统,叫做UTC,即协调世界时。是一种以原子钟为基础的时间计量系统。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9192631770周所持续的时间为1秒。
当原子钟计时一天的时间与地球自转一周的时间相差超过0,9秒时,UTC会执行闰秒来保证其计时与地球自转的协调一致。
闰秒:计时标准是恒定不变的,但是地球越转越慢,误差超过0.9秒时,计时系统就多走一秒来等一下地球的自转。
时间戳转换
C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便地进行秒计数器、日期时间和字符串之间的转换。
函数 | 作用 |
time_t time(time_t *seconds) | 获取系统时钟 |
struct tm *gmtime(const time_t *timer) | 秒计数器转换为日期时间(格林尼治时间) |
struct tm *localtime(const time_t *timer) | 秒计数器转换为日期时间(当地时间) |
time_t mktime(struct tm *timeptr) | 日期时间转换为秒计数器(当地时间) |
char *ctime(const time_t *timer) | 秒计数器转换为字符串(默认格式) |
char *asctime(const struct tm *timeptr) | 日期时间转换为字符串(默认格式) |
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr) | 日期时间转换为字符串(自定义格式) |
数据类型:
1、秒计数器时间类型:time_t,64位有符号的整型数据,用于存储时间戳中一直自增的秒数。
2、日期时间类型:struct tm,是一个结构体,具体如下:
3、字符串时间类型:char*,就是char类型数据的指针。用来指向一个表示时间的字符串。
BKP简介
BKP备份寄存器,可用于存储用户应用程序数据,当VDD(2.0~3.6V)电源被切断,他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位(除非VBAT掉电)。
用户数据存储容量:
20字节 | 中容量和小容量 |
84字节 | 大容量和互联型 |
对于C8T6芯片,为中容量,对应20字节。可以看出BKP的容量其实非常小,一般只能存储少量的参数。
BKP基本结构
- 后备区域
图中的橙色部分,我们可以叫做后备区域。注意,是BKP处于后备区域,但后备区域不只有BKP,还有RTC的相关电路。
STM32后备区域的特性就是:当VDD主电源掉电时,后备区域仍然可以由VBAT的备用电池供电;当VDD上电时,后备区域供电会由VBAT切换为VDD,可以节省电池电量。
- 内部寄存器
BKP里主要有状态寄存器、控制寄存器、数据寄存器、RTC时钟校准寄存器。其中数据寄存器是主要部分,用来存储数据的。每个数据寄存器都是16位的(一个数据寄存器可以存2个字节),对于中容量和小容量的设备,里面有DR1~DR10总共10个数据寄存器,共20个字节。
- 侵入检测
BKP可以从PC13位置的TAMPER引脚引入一个检测信号,当TAMPER产生一个上升沿或者下降沿时,会清除BKP所有的内容,以保证安全。
- 时钟输出
将RTC的相关时钟从PC13位置的RTC引脚输出出去,供外部使用。其中,输出校准时钟时,再配合RTC时钟校准寄存器,可以对RTC的误差进行校准。
RTC简介
RTC即实时时钟,STM32中RTC是一个独立的定时器,可为系统提供时钟和日历(年月日时分秒)的功能。
RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD(2.0~3.6V)断电后可借助VBAT(1.8~3.6V)供电继续走时。
- 秒计数器与分频器
在RTC中,负责计数的装置只有一个32位的秒计数器。且1秒就要自增一次,所以驱动秒计数器的时钟---TR_CLK是一个1Hz的信号。但实际提供给RTC的时钟,也就是RTCCLK,一般频率都比较高。所以显然需要在这之间加一个分频器,保证输出给计数器的频率为1Hz。
RTC中的预分频器,是一个20位的分频器(可编程),可以选择对输入时钟进行1~2^20分频,这样可以适配不同频率的输入时钟。
- RTC时钟源
RTCCLK的来源主要有以下3种:
HSE时钟除以128 | 8MHz/128 |
LSE振荡器时钟 | 37.768KHz |
LSI振荡器时钟 | 40KHz |
其中HSE是高速外部时钟信号(通常为高速晶振)、LSE低速外部时钟信号、LSI低速内部时钟信号。具体可参考RCC章节知识。
RTC框图
左边阴影区为核心的分频和计数区域,右边为中断输出使能和NVIC部分,上面为APB1总线读写部分,下面阴影区是与PWR关联的部分。(阴影区均为后备区域)