13 BKP和RTC

前言

这一节主要是讲解RTC时钟和BKP内部寄存器的,代表着单片机裸机开发就快结束了,后面可能会出RTOS的教程。

一、BKP备份寄存器

1.BKP介绍

该寄存器是在stm32内部的一个RAM寄存器,需要在外部为单片机的VBT引脚接一个电池,保证内部的BKP寄存器中的数据不丢失。

当系统在待机模式下被唤醒,或系统复位或电源复位时,BKP也不会被复位。

TAMPER引脚产生的侵入事件将所有备份寄存器内容清除,保障重要的内容在被入侵时清空。

在小容量或者中等容量的单片机中该寄存器中用户可以存放20字节的数据,在大容量和互联型设备中可以存放84字节的数据。

2.BKP的使用

BKP是挂载到APB1总线上的设备,所以需要使用RCC_APB1PeriphClockCmd()来对BKP进行时钟的打开。

BKP需要PWR电源管理设备的配合使用,所以还需要打开一下PWR的时钟,PWR的时钟也是挂载到APB1总线上的,所以这里就知道了,先打开BKP的时钟,然后再打开PWR的时钟。

最后使能一下PWR,这样就可以对BPK进行使用了。

这里直接上代码:

1
2
3
4
5
6
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //开启PWR的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE); //开启BKP的时钟

/*备份寄存器访问使能*/
PWR_BackupAccessCmd(ENABLE); //使用PWR开启对备份寄存器的访问

这样就可以对BKP进行使用了,对于寄存器的使用其实就是读取和写入,我们可以使用BKP_WriteBackupRegister()函数对对应的BKP位置写入数据。

然后使用BKP_ReadBackupRegister()函数读取对应BKP寄存器中的位置的数据。

二、RTC实时时钟

这个是这一节的重点,前面的BKP是和RTC连在一起的,因为都是由VBT引脚进行独立供电的设备。

1.RTC时钟的介绍

RTC是一个独立的定时器,可为系统提供时钟和日历的功能,断电不丢失,由VBT引脚提供电源来进行运行。

32位的可编程计数器,可对应Unix时间戳的秒计数器。20位的可编程预分频器,可适配不同频率的输入时钟

可选择三种RTC时钟源:

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

2.RTC内部结构

img

这个是RTC的内部框图,可以看到RTC是挂载到APB1总线上的,由RTCCLK输入频率后开始计时,对Unix时钟戳继续计数值。

我们可以通过RTC来让STM32从待机模式中退出。

外部时钟通过RTCCLK进行选择后输入到RTC预分频器中进行分频。

3.RTC代码编写的注意事项

对RTC时钟的开启也是需要通过打开PWR和BKP的时钟的,打开后还需要使能PWR,使得BPK和RTC都能使用。

在写入RTC的寄存器前需要使RTC进入配置模式后才能写入RTC的RTC_PRL、RTC_CNT、RTC_ALR寄存器,当写完后还需要退出RTC的配置模式。

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

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

4.代码的实现

这里直接就上代码吧,本质上来说RTC的操作还是比较的简单的,这里就不细说了,注意等待同步和等待上一次操作完成即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);		//开启PWR的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE); //开启BKP的时钟RCC_LSEConfig(RCC_LSE_ON); //开启LSE时钟
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET); //等待LSE准备就绪

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择RTCCLK来源为LSE
RCC_RTCCLKCmd(ENABLE); //RTCCLK使能

RTC_WaitForSynchro(); //等待同步
RTC_WaitForLastTask(); //等待上一次操作完成

RTC_SetPrescaler(32768 - 1); //设置RTC预分频器,预分频后的计数频率为1Hz
RTC_WaitForLastTask(); //等待上一次操作完成RTC_WaitForSynchro(); //等待同步
RTC_WaitForLastTask(); //等待上一次操作完成