跳到主要内容

RTC实时时钟

1. Unix时间戳

Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒

时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量

世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间

Image

2. GMT/UTC

GMT(Greenwich Mean Time)格林尼治标准时间是一种以地球自转为基础的时间计量系统。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准

UTC(Universal Time Coordinated)协调世界时是一种以原子钟为基础的时间计量系统。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间为1秒。当原子钟计时一天的时间与地球自转一周的时间相差超过0.9秒时,UTC会执行闰秒来保证其计时与地球自转的协调一致

3. 时间戳转换

C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便地进行秒计数器、日期时间和字符串之间的转换

time.h参考: https://www.runoob.com/cprogramming/c-standard-library-time-h.html

Image

time_t是一个typedef重命名的类型,time_t默认是__time64_t,实际上是int64类型。

4. BKP备份寄存器

BKP(Backup Registers)备份寄存器。BKP可用于存储用户应用程序数据。当VDD(2.0~3.6V)电源被切断,他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位。

危险

BKP本质上是RAM存储器,所以是掉电丢失的!

TAMPER引脚产生的侵入事件将所有备份寄存器内容清除.

RTC引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲

存储RTC时钟校准寄存器

用户数据存储容量: 20字节(中容量和小容量)/ 84字节(大容量和互联型)

Image

备用电池只有一根正极的供电引脚,接电池时,电池正极接到VBAT,电池负极和主电源的负极接在一起,共地。

VBAT引脚直接通过板子引出,不接电池则引脚悬空。STM32手册建议:如果没有外部电池供电,建议VBAT引脚接到VDD,即和主电源接到一起,接一个100nF的滤波电容。

配合TAMPER引脚,可以做有防拆功能的设备。敏感数据存在BKP里面,使能TAMPER引脚的侵入检测功能。

提示

设计时,TAMPER引脚可以先加一个默认的上拉或者下拉电阻,引一根线到设备外壳的防拆开关或触点。

此时,一旦拆开设备,就会在TAMPER引脚产生上升沿或者下降沿。检测到侵入事件后,BKP自动清零(清掉自己所有的数据),申请中断,在中断里可以继续保护设备。

主电源断电后,侵入检测依然有效,设备关机也能防拆。

橙色区域为后备区域,当VDD主电源掉电时,后备区域仍然可以由VNAT的备用电池供电;VDD上电时,后备区域供电会由VBAT切换到VDD,即:主电源有电时,VBAT不会用到,节省电池电量。

每个数据寄存器都是16位的,有DR1-DR10总共10个数据寄存器。如果是大容量的互联型设备,就不止有10个寄存器,而是有42个寄存器(84字节)。

5. RTC时钟

RTC(Real Time Clock)实时时钟,RTC是一个独立的定时器,可为系统提供时钟和日历的功能

RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD(2.03.6V)断电后可借助VBAT(1.83.6V)供电继续走时

32位的可编程计数器,可对应Unix时间戳的秒计数器

20位的可编程预分频器,可适配不同频率的输入时钟

可选择三种RTC时钟源:

  1. HSE时钟除以128(通常为8MHz/128)
  2. LSE振荡器时钟(通常为32.768KHz)
  3. LSI振荡器时钟(40KHz)

Image

上边的是APB总线部分,左边和灰色是后备区域部分,右边是NVIC部分,下边是PWR(电源控制)关联部分。

后备区域可以在主电源掉电后继续操作。在待机时,都会继续维持供电。这一块的输入时钟是RTCCLK(在RCC中配置)。

RTC_PRL是重装载寄存器,用来配置计数目标,重装值写入几,就是几+1分频;RTC_DIV叫做余数寄存器,但实际上是和计数器CNT和重装值ARR发挥了一样的作用,还是一个自减计数器,用来配置几分频,自减到0时再来一个输入时钟,DIV输出一个脉冲,产生溢出信号,同时DIV从PRL获取重装值,回到重装值继续自减。

提示

如果想要的是1Hz的分频,那么PRL给32767, DIV给0,这样当第一个输入时钟到来时,DIV立刻溢出给出溢出信号,变为重装值32767。之后来一个时钟就自减一次,减到0,那就又变成32767。

RTC_CNT可以看作是Unix时间戳的秒计数器。

RTC_ALR是闹钟寄存器,ALR是一个32位的寄存器。和CNT是等宽的。在ALR写一个秒数可以设定闹钟,当RTC_CNT=RTC_ALR时,闹钟信号就会产生,通往右边的RTC_CR。

提示

闹钟信号可以让STM32退出待机模式。

比如设计一个数据采集设备,需要在非常恶劣的条件下工作,要求是每天中午12点采集一次环境数据,其他时间为了节省电量待机,这个时候,就可以设置一个这个闹钟了。

RTC_Second是秒中断,其来源是CNT的输入时钟。如果开启该中断,那么程序会每秒进一次RTC中断。

RTC_Overflow是溢出中断,其来源是CNT的右边,即CNT的32位计数器计满溢出,会触发一次中断。

信息

但是这个中断一般不会溢出,因为CNT定义是无符号数,到2106年才会溢出。

如果你是个立志活到2106年的嵌入式开发者,你可以开启该中断,接到溢出信号时,设置提示。在2106年时,你就可以看到他老去的样子。

看右边的NVIC,F结尾的对应中断标志位,IE结尾的是中断使能,3个刚刚提到的中断信号通过一个或门,汇聚到NVIC中断控制器。

上边是APB总线,控制寄存器的读写。

下边的WKUP引脚,兼具唤醒的功能。

Image

6. 硬件电路

Image

在STM32最小系统的外部还得加备用电池和外部低速晶振。

可以使用右边的推荐连接,比较稳健。

7. RTC操作注意事项

执行以下操作将使能对BKP和RTC的访问:

  • 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
  • 设置PWR_CR的DBP,使能对BKP和RTC的访问

若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1。(初始化的时候,调用一个等待函数)

必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器。

**对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。**可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器。(因为PCLK1的频率写入之后,这个值还不能立刻更新到RTC的寄存器里,因为RTC寄存器是由RTCCLK驱动的,PCLK1写完之后,得等RTCCLK的时钟,RTCCLK来一个上升沿,值更新到RTC寄存器里,写入过程才算结束。代码中,可以调用一个等待函数。)