2.41 BKP备份寄存器&RTC实时时钟

BKP简介

BKP(Backup Registers)备份寄存器 BKP可用于存储用户应用程序数据。

BKP是怎么做到掉电不丢失的?

当VDD(2.0~3.6V)电源(VDD是主电源)被切断,他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位。如果要使用STM32内部的BKP和RTC,这个VBAT引脚就必须接备用电池,用来维持BKP和RTC,在VDD主电源掉电后的供电。这里的备用电池只有一根正极的供电引脚,接电池时,电池正极接到VBAT,电池负极和主电源的负极接在一起共地就行了。

简单来说就是,VBAT的作用就是当VDD断电时,BKP会切换到VBAT供电,这样就可以继续维持BKP里面的数据。

如果主电源VDD和VBAT都断电了,那么BKP里面的数据就会清零。因为BKP本质上是RAM存储器,没有掉电不丢失的能力。

TAMPER引脚产生的侵入事件将所有备份寄存器内容清除。这个引脚是一个安全保障设计,比如你做一个安全系数非常高的设备,设备需要有防拆功能,然后BKP里也存储了一些敏感数据,不能被别人窃取或者篡改,就可以使用TAMPER引脚的侵入检测功能。

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

存储RTC时钟校准寄存器。

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

BKP的基本结构

后备区域有:数据寄存器、控制寄存器、状态寄存器和RTC时钟校准寄存器。

BKP处于后备区域,但后备区域不只有BKP,还有RTC相关的电路。STM32后备区域的特性就是,当VDD主电源掉电时,后备区域仍然可以由VBAT的备用电池供电。当VDD主电源上电时,后备区域供电会由VBAT切换到VDD。

后备区域中数据寄存器是主要部分,每个数据寄存器都是16位的,也就是1个数据寄存器可以存2个字节。

RTC实时时钟

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

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

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

20位的可编程预分频器,可适配不同频率的输入时钟。(32位的秒计数器,显然1秒要自增1次,所以需要1HZ的信号来驱动秒计数器,但是实际提供给RTC模块的时钟(RTCCLK),一般频率都比较高,所以要加一个RTC预分频器)

可选择三种RTC时钟源:

HSE时钟除以128(通常为8MHz/128)

LSE振荡器时钟(通常为32.768KHz)

LSI振荡器时钟(40KHz)

最常用的是LSE,低速外部时钟信号。

为什么使用LSE?

因为32.768KHz,正好是2的15次方,只需要设计一个2的15次方的寄存器,让计数器自然溢出,不用设定目标值,这样就简化了电路的设计。并且LSE是专门用于RTC时钟源的。

还有一个更重要的原因就是,只有LSE这一路的时钟,可以通过VBAT备用电池供电。

有灰色填充的区域,都是后备区域,这些电路在主电源掉电后,可以使用备用电池维持工作,这些模块在待机时都会继续维持供电。

RTC还设计有一个闹钟寄存器(RTC_ALR),这个ALR也是一个32位寄存器,和上面的RTC_CNT是等宽的,它的作用顾名思义就是设置闹钟,我们可以在ALR写一个秒数,设定闹钟,当CNT的值跟ALR设定的闹钟值一样时,就会产生RTC_Alarm信号,通往右边的中断系统。同时这个闹钟信号也可以让STM32退出待机模式。

有三个信号可以触发中断:

RTC_Second,秒中断,它的来源,就是CNT的输入时钟,如果开启这个中断,程序就会每秒进一次RTC中断。

RTC_Overflow,溢出中断,意思就是32位计数器计满溢出了,会触发一次中断,所以这个中断一般不会触发。

RTC_Alarm,闹钟中断,当计数器和闹钟值相等时,触发中断。

RTC基本结构

,这是RTCCLK时钟来源,需要在RCC里配置,3个时钟,选择1个,当做RTCCLK。之后RTCCLK先通过预分频器,对时钟进行分频得到1HZ信号。

以上就是STM32 RTC的内部电路,内部电路清楚了,外部电路也需要了解:

为了配合STM32的RTC,外部还是需要有一些电路的,在最小系统电路上,外部电路还要额外加两部分,第一部分就是备用电池,第二部分就是外部低俗晶振。

RTC操作注意事项

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

设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟。

设置PWR_CR的DBP,使能对BKP和RTC的访问。

正常的外设,第一步开启时钟就能用了,但是BKP和RTC这两个外设,开启稍微复杂一些,首先要设置RCC_APB1ENR(开启APB1外设的时钟),要同时开启PWR和BKP的时钟。对于RTC来说,并没有单独开启时钟的选项。

 

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

为什么要有这一步呢?

图中有两个时钟,一个是RTCCLK,另一个是PCLK1。PCLK1在主电源掉电时会停止,所以为了保证RTC主电源掉电正常工作,RTC里的寄存器都是在RTCCLK的同步下变更的,当我们用PCLK1驱动的总线,去读取RTCCLK驱动的寄存器时,就会有个时钟不同步的问题,RTC寄存器,只有在RTCCLK的上升沿更新,但是PCLK1的频率36MHz,远大于RTCCLK的频率32KHz,如果我们在APB1刚开启时,就立刻读取RTC寄存器,有可能RTC寄存器还没有更新到APB1总线上,这样我们读到的值就是错误的(通常读取到的是0)。

所以这就要求,我们在APB1总线刚开启时,要等一下RTCCLK,只要RTCCLK来一个上升沿,RTC把他的寄存器的值同步到APB1总线上,这样之后读取的值就都是没问题的了。

当然我们其实也不用管那么多,只需要在初始化时,调用一个等待同步的函数就行了。

 

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

RTC会有一个进入配置模式的标志位,把这一位置1,才能设置时间,其实这个操作在库函数中,每个写寄存器的函数,他都自动帮我们加上了这个操作,所以我们就不用再单独调用代码,进入配置模式了。

 

4.对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器。

其实也是调用一个等待函数,跟我们之前读写Flash芯片类似,就是写入之前,要等待一下。

为什么要有这个操作呢?

其实还是因为这里的PCLK1和RTCCLK时钟频率不一样,你用PCLK1的频率写入后,这个值还不能立刻更新到RTC的寄存器里,因为RTC寄存器是由RTCCLK驱动的,所以PCLK1写完之后,得等一下RTCCLK的时钟,RTCCLK来一个上升沿,值更新到RTC寄存器里,整个写入过程才算结束了。