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

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

BKP简介

PC13-TAMPER-RTC,PC13,TAMPER,RTC3个功能共用一个引脚。所以这3个功能同一时间,只能使用一个。

  • BKP(Backup Registers)备份寄存器,BKP就是一些存储器,可以存储自定义的数据。

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

    • 如果要使用STM32内部的BKP和RTC,这个VBAT引脚就必须接备用电池,用来维持BKP和RTC,在VDD主电源掉电后的供电。这里备用电池只有一根正极的供电引脚,接电池时,电池正极接到VBAT,电池负极和主电源的负极接在一起,共地,就行了。
    • VBAT的作用就是,当VDD断电时,BKP会切换到VBAT供电,这样可以继续维持BKP里面的数据,如果VDD断电,VBAT也没电,那BKP里的数据就会清零,因为BKP本质上是RAM存储器,没有掉电不丢失的能力。
  • TAMPER引脚产生的侵入事件将所有备份寄存器内容清除。

    • TAMPER引脚,是一个安全保障设计,比如如果做一个安全系数非常高的设备,设备需要有防拆功能,然后BKP里也存储了一些敏感数据,这些数据不能被别人窃取或者篡改,就可以使用TAMPER引脚的侵入检测功能,设计电路时,TAMPER引脚可以先加一个默认的上拉或者下拉电阻,然后引一根线,到设备外壳的防拆开关或触点,别人一拆开你的设备,触发开关,就会在TAMPER引脚产生上升沿或者下降沿,这样STM32就检测到侵入事件了,这时BKP的数据会自动清零,并且申请中断。在中断中,可以继续保护设备,比如清除其他存储器数据,然后设备锁死,来保障设备的安全。
    • 主电源断电后,侵入检测仍然有效。即使设备关机也能防拆。
  • RTC引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲

    • 外部用设备测量RTC校准时钟,可以对内部RTC微小的误差进行校准。
    • 闹钟脉冲或者秒脉冲,可以输出出来,为别的设备提供这些信号。
  • 存储RTC时钟校准寄存器,可以配合校准时钟输出的功能,结合一些测量方法,对RTC进行校准。

  • 用户数据存储容量:

    • 20字节(中容量和小容量)/ 84字节(大容量和互联型)
    • BKP的容量其实非常小,一般只能用来存储少量参数。

BKP基本结构

  • BKP处于后备区域,但后备区域还有RTC的相关电路。STM32的后备区域,当VDD主电源掉电时,后备区域仍然可以由VBAT的备用电池供电,当VDD主电源上电时,后备区域供电会由VBAT切换到VDD,也就是主电源有电时,VBAT不会用到,这样可以节省电池电量。
  • BKP里主要有数据寄存器、控制寄存器、状态寄存器和RTC时钟校准寄存器这些东西。其中数据寄存器是主要部分,用来存储数据。每个寄存器都是16位的,也就是一个数据寄存器可以存2个字节。
    • 对于中容量和小容量的设备,里面有DR1,DR2一直到DR10,总共10个数据寄存器,一个寄存器存两个字节,所以容量是20个字节。
    • 对于大容量和互联型设备,里面除了DR1到DR10,还有DR11、DR12一直到DR42,总共42个数据寄存器,容量是84个字节。
  • BKP的一些功能
    • 侵入检测,可以从PC13位置的TAMPER引脚引入一个检测信号,当TAMPER产生上升沿或者下降沿时,清除BKP所有的内容,以保证安全。
    • 时钟输出,可以把RTC的相关时钟,从PC13位置的RTC引脚输出出去,供外部使用。其中输出校准时钟时,再配合这个校准寄存器,可以对RTC的误差进行校准。

STM32 BKP备份寄存器&RTC实时时钟_第1张图片

RTC简介

  • RTC(Real Time Clock)实时时钟

  • RTC是一个独立的定时器,可为系统提供时钟和日历的功能,一般指提供年月日时分秒这种日期时间信息的计时装置。

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

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

    • 在读取时间时,我们先得到这个秒数,然后使用time.h模块里的localtime函数,就能立刻知道年月日时分秒的信息了。
    • 在写入时间时,我们先填充年月日时分秒信息到struct tm结构体,然后用mktime函数,得到秒数,再写入到这个32位计数器即可。
  • 20位的可编程预分频器,可适配不同频率的输入时钟

    • 32位的秒计数器,显然要1秒自增一次,所以驱动计数器的时钟,需要是一个1HZ的信号,但是实际提供给RTC模块的时钟,也就是RTCCLK,一般频率都比较高,所以显然,需要在输入时钟和秒计数器之间加一个分频器,给RTCCLK降频,保证分频器输出给计数器的频率为1HZ。
    • 为了适配各种频率的RTCCLK,这里就加了一个20位的分频器,可以选择对输入时钟进行1~220这么大范围的分频,这样就可以适配不同频率的输入时钟。
  • 可选择三种RTC时钟源:高速时钟一般供内部程序运行和主要外设使用;低速时钟,一般供RTC、看门狗这些东西使用。

    • HSE时钟除以128(通常为8MHz/128)高速外部时钟信号
      • 外部高速晶振,一般都用的8MHZ,8MHZ进来,通过128分频,可以产生RTCCLK信号。由于8MHZ的主晶振太快了,如果不提前分频,直接给RTCCLK,后续即使再通过RTC的20位分频器,也分不到1HZ这么低的频率。所以8MHZ,提前进行128分频,后续20位的分频器,再进行一个适当的分频,就可以输出1HZ的信号给计数器了。
    • LSE振荡器时钟(通常为32.768KHz)最常用 低速外部时钟信号 RTC电路中,基本都是清一色的32.768KHZ的晶振。
      • 外部低速晶振,这个晶振产生的时钟,可以直接提供给RTCCLK,这个OSC32的晶振,是内部RTC的专用时钟,通常跟RTC有关的晶振,频率就是32.768KHZ。32768正好是215,所以32.768KHZ,经过一个15位分频器的自然溢出,就能很方便的得到1HZ的频率。自然溢出的意思就是设计一个15位的计数器,这个计数器不用设置一个计数目标,直接从0计到最大值,就是计到32767,计满后自然溢出,这个溢出信号就是1HZ。自然溢出的好处就是不用再额外设计一个计数目标了,也不用比较,计数器是否达到目标值,可以简化电路设计。
    • LSI振荡器时钟(40KHz)低速内部时钟信号
      • 内部低速RC振荡器,固定是40KHZ,后续再经过40K的分频,就能得到1HZ的计数时钟了。内部的RC振荡器,一般精度没有外部晶振高。

一般都是使用LSE振荡器时钟,外部32.768KHZ的晶振,提供RTCCLK的时钟。

  • 32.768KHZ的晶振,本身就是专供RTC使用的。
    • 其他两个时钟都有各自的任务,HSE时钟主要作为系统主时钟;LSI振荡器时钟,主要作为看门狗时钟。它们只是顺带可以备选当作RTC的时钟。
    • 只有LSE振荡器时钟,可以通过VBAT备用电池供电,HSE时钟和LSI振荡器时钟在主电源断电后是停止运行的,所以要想实现RTC主电源掉电继续走时的功能,必须得选择LSE振荡器时钟(RTC的专用时钟)。如果选择的是HSE时钟或者LSI振荡器时钟,主电源断电后,时钟就暂停了。这显然会导致走时出错。

RTC框图

  • 图中有灰色填充的部分,都处于后备区域,这些电路在主电源掉电之后,可以使用备用电池维持工作。
  • 分频和计数计时部分,输入时钟是RTCCLK,RTCCLK的来源需要在RCC里进行配置,可以选择HSE时钟除以128、LSE振荡器时钟、LSI振荡器时钟作为时钟源。RTCCLK首先经过RTC预分频器进行分频,这个预分频器由两个寄存器组成:重装载寄存器RTC_PRL和余数寄存器RTC_DIV。但实际上这两个寄存器和之前定时器时基单元中的计数器CNT和重装载ARR是同样的作用。
    • 分频器其实就是一个计数器,记几个数溢出一次,就是几分频。所以对于可编程的分频器来说,需要有两个寄存器,一个寄存器用来不断地计数,另一个寄存器,我们写入一个计数目标值,用来配置是几分频。
      • PRL就是计数目标,写入6,就是7分频,写入9,就是10分频,因为计数值包含了0,所以重装值写入几,就是几+1分频。
      • DIV就是每来一个时钟计一个数的用途了,这个DIV计数器其实是一个自减计数器,每来一个输入时钟,DIV的值就自减一次,自减到0时,再来一个输入时钟,DIV输出一个脉冲,产生溢出信号,同时DIV从PRL获取重装值,回到重装值继续自减。

举个例子,比如RTCCLK,输入时钟是32.768KHZ,即32768HZ,为了分频之后得到1HZ,PRL就要给32767,这个数值始终不变,DIV可以保持初始值为0。在第一个输入时钟到来时,DIV就立刻溢出,产生溢出信号给后续电路,同时,DIV变为重装值32767,然后第二个输入时钟,DIV自减为32766,第三个时钟变为32765,之后,来一个输入时钟自减一次,直到变为0。然后再来一个输入时钟,就会产生一个溢出信号,同时DIV回到32767。依次往复循环。这样,就是每来32768个输入脉冲,计数器溢出一次,产生一个输出脉冲,这就是32768分频,分频后输出的时钟频率是1HZ,提供给后续的秒计数器。

  • 32位可编程计数器RTC_CNT,就是计时最核心的部分,可以把这个计数器看作是Unix时间戳的秒计数器,再借助time.h的函数,就可以很方便地得到年月日时分秒了。
  • 闹钟寄存器RTC_ALR,32位寄存器,我们可以在ALR写一个秒数,设定闹钟,当CNT的值跟ALR设定的闹钟值一样时,闹钟响应,产生RTC_Alarm闹钟信号,通往中断系统,在中断函数中,再执行相应操作。同时,闹钟信号还可以让STM32退出待机模式。

比如设计一个数据采集设备,需要在环境非常恶劣的地方工作,像海底、高原、深井这些地方,要求每天中午12点采集一次环境数据,其他时间,为了节省电量,避免频繁换电池,芯片都必须处于待机模式。这样,我们就可以用RTC自带的闹钟功能,定一个中午12点的闹钟,闹钟一响,芯片唤醒,采集数据,完成后,继续待机。另外,这个闹钟值是一个定值,只能响一次,如果想实现周期性的闹钟,那在每次闹钟响之后,都需要再重新设置一下下一个闹钟的时间。

  • 中断,有3个信号可以触发中断。最后三个信号通过一个或门,汇聚到NVIC中断控制器。
    • RTC_Second 秒中断,它的来源,就是CNT的输入时钟,如果开启这个中断,那么程序每秒就会进一次RTC中断。
    • RTC_Overflow 溢出中断,它的来源,是CNT的右边,意思就是CNT的32位计数器记满溢出了,会触发一次中断,所以这个中断一般不会触发。(这个CNT定义是无符号数,到2106年才会溢出)
    • RTC_Alarm 闹钟中断,当计数器和闹钟值相等时,触发中断,同时,闹钟信号可以把设备从待机模式唤醒。
  • APB1总线和APB1接口,就是程序读写寄存器的地方了,读写寄存器,可以通过APB1总线来完成。
  • WKUP(Weak Up)引脚,可以唤醒设备。

STM32 BKP备份寄存器&RTC实时时钟_第2张图片

RTC基本结构

  • RTCCLK时钟来源,需要在RCC里配置,3个时钟选择一个作为RTCCLK的时钟源。
    • HSE/128 外部高速时钟
    • LSE 外部低速时钟
    • LSI 内部低速时钟
  • RTCCLK先通过预分频器对时钟进行分频,分频之后得到1HZ的秒计数信号,通向32位计数器,1秒自增1次。
    • 余数寄存器是一个自减计数器,存储当前的计数值
    • 重装计数器是计数目标,决定分频值
  • 32位闹钟值,可以设定闹钟。
  • 有3个信号可以触发中断,3个信号先通过中断输出控制,进行中断使能,使能的中断才能通向NVIC,然后向CPU申请中断
    • 秒信号
    • 计数器溢出信号
    • 闹钟信号

在程序中

  • 配置数据选择器,可以选择时钟来源
  • 配置重装寄存器,可以选择分频系数
  • 配置32位计数器,可以进行日期时间的读写
  • 配置32位闹钟值,可以配置闹钟
  • 需要中断的话,先允许中断,再配置NVIC,最后写对应的中断函数

STM32 BKP备份寄存器&RTC实时时钟_第3张图片

硬件电路

  • 备用电池供电部分
    • 简单连接,使用一个3V的电池,负极和系统共地,正极直接引到STM32的VBAT引脚。
      • STM32内部有一个供电开关,当VDD有电时,开关拨到下面,后备电路由VDD供电;当VDD没电时,开关拨到上面,后备电路由VBAT供电。VBAT供电的后备电路有32KHZ振荡器、RTC唤醒电路、后备寄存器。
    • 推荐连接,电池通过二极管D1,向VBAT供电,另外主电源的3.3V,也通过二极管D2,向VBAT供电,最后VBAT再加一个0.1uF的电源滤波电容。
      • 电池和主电源都加一个二极管,防止电流倒灌。如果没有备用电池,就是3V3的主电源供电,如果接了备用电池,3V3没电时,就是备用电池供电。
  • 外部低速晶振,两端分别接在OSC32这两个引脚上,然后晶振两端,再分别接一个起振电容到GND。

STM32 BKP备份寄存器&RTC实时时钟_第4张图片

RTC操作注意事项

  • 执行以下操作将使能对BKP和RTC的访问:
    • 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
    • 设置PWR_CR的DBP,使能对BKP和RTC的访问

正常的外设,第一步开启时钟就可以使用,但是BKP和RTC这两个外设,首先要设置RCC_APB1ENR,这个实际上就是开启APB1外设的时钟,要同时开启PWR和BKP的时钟,对于RTC来说,并没有单独开启时钟的选项。然后,还要设置PWR_CR的DBP位,来使能对BKP和RTC的访问,这个调用PWR的函数,开启一下即可。

总结一下就是,如果你要使用BKP或者RTC,都要先执行这两步:

  • 第一步,开启PWR和BKP的时钟
  • 第二步,使用PWR,使能BKP和RTC的访问
  • 若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1
    • 这一步对应代码中的一个库函数,就是RTC等待同步,一般在刚上电的时候调用一下这个函数就可以。
      • 由于PCLK1在主电源掉电时会停止,所以为了保证RTC主电源掉电正常工作,RTC里的寄存器都是在RTCCLK的同步下变更的,当我们用PCLK1驱动总线,去读取RTCCLK驱动的寄存器时,就会有一个时钟不同步的问题,RTC寄存器,只有在RTCCLK的上升沿更新,但是PCLK1的频率为36MHZ,远大于RTCCLK的频率32.768KHZ,如果我们在APB1刚开启时,就立刻读取RTC寄存器,有可能RTC寄存器还没有更新到APB1总线上,这样我们读到的值就是错误的。所以这就要求我们在APB1总线刚开启时,要等一下RTCCLK,只要RTCCLK来一个上升沿,RTC把它的寄存器的值同步到APB1总线上,这样之后读取的值就没问题了。
  • 必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器
    • 就是RTC会有一个进入配置模式的标志位,把这一位置1,才能设置时间,其实在库函数中,每个写寄存器的函数,都自动帮我们加上了这个操作,所以我们就不用单独调用代码,进入配置模式了。
  • 对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器
    • 其实还是因为,PCLK1和RTCCLK时钟频率不一样,用PCLK1的频率写入之后,这个值还不能立刻更新到RTC的寄存器里,因为RTC寄存器是由RTCCLK驱动的,所以PCLK1写完之后,得等待一下RTCCLK的时钟,RTCCLK来一个上升沿,值更新到RTC寄存器里,整个写入过程才算结束

你可能感兴趣的:(STM32,教程,stm32,实时音视频,单片机,嵌入式硬件)