一、RTC相关介绍
RTC实时时钟简介:
STM32的RTC外设,实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断).但是从掉电还能继续运行来看,它是STM32中唯一一个具有这个功能功能的外设.(RTC外设的复杂之处不在于它的定时,而在于它掉电还可以继续运行的特性)
所谓掉电,是指电源Vpp断开的情况下,为了RTC外设掉电可以继续运行,必须给STM32芯片通过VBAT引脚街上锂电池.当主电源VDD有效时,由VDD给RTC外设供电.当VDD掉电后,由VBAT给RTC外设供电.无论由什么电源供电,RTC中的数据始终都保存在属于RTC的备份域中,如果主电源和VBA都掉电,那么备份域中保存的所有数据都将丢失.(备份域除了RTC模块的寄存器,还有42个16位的寄存器可以在VDD掉电的情况下保存用户程序的数序,系统复位或电源复位时,这些数据也不会被复位).
从RTC的定时器特性来说,它是一个32位的计数器,只能向上计数.他使用的时钟源有三种,分别为:
- 高速外部时钟的128分频:HSE/128;
- 低速内部时钟LSI;
- 低速外部时钟LSE;
使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE,频率为实时时钟模块中常用的32.768KHz,因为32768 = 2^15,分频容易实现,所以被广泛应用到RTC模块.(在主电源VDD有效的情况下(待机),RTC还可以配置闹钟事件使STM32退出待机模式).
RTC工作过程:
RTC架构:
图中浅灰色的部分都是属于备份域的,在VDD掉电时可在VBAT的驱动下继续运行.这部分仅包括RTC的分频器,计数器,和闹钟控制器.若VDD电源有效,RTC可以触发RTC_Second(秒中断)、RTC_Overflow(溢出事件)和RTC_Alarm(闹钟中断).从结构图可以看到到,其中的定时器溢出事件无法被配置为中断.如果STM32原本处于待机状态,可由闹钟事件或WKUP事件(外部唤醒事件,属于EXTI模块,不属于RTC)使它退出待机模式.闹钟事件是在计数器RTC_CNT的值等于闹钟寄存器RTC_ALR的值时触发的.
因为RTC的寄存器是属于备份域,所以它的所有寄存器都是16位的.它的计数RTC_CNT的32位由RTC_CNTL和RTC_CNTH两个寄存器组成,分别保存计数值的低16位和高16位.在配置RTC模块的时钟时,把输入的32768Hz的RTCCLK进行32768分频得到实际驱动计数器的时钟TR_CLK = RTCCLK/37768 = 1Hz,计时周期为1秒,计时器在TR_CLK的驱动下计数,即每秒计数器RTC_CNT的值加1(常用)
由于备份域的存在,使得RTC核具有了完全独立于APB1接口的特性,也因此对RTC寄存器的访问要遵守一定的规则.
系统复位后,禁止访问后备寄存器和RCT,防止对后卫区域(BKP)的意外写操作.(执行以下操作使能对后备寄存器好RTC的访问):
1,设置RCC_APB1ENR寄存器的PWREN和BKPEN位来使能电源和后备接口时钟.
2,设置PWR_CR寄存器的DBP位使能对后备寄存器和RTC的访问.
设置为可访问后,在第一次通过APB1接口访问RTC时,必须等待APB1与RTC外设同步,确保被读取出来的RTC寄存器值是正确的,如果在同步之后,一直没有关闭APB1的RTC外设接口,就不需要再次同步了.
如果内核要对RTC寄存器进行任何的写操作,在内核发出写指令后,RTC模块在3个RTCCLK时钟之后,才开始正式的写RTC寄存器操作.我们知道RTCCLK的频率比内核主频低得多,所以必须要检查RTC关闭操作标志位RTOFF当这个标志被置1时,写操作才正式完成.
(以上操作在STM32库里面都有库函数,不需要具体的查阅寄存器~~~~)
UNIX时间戳:
假如从现在起,把计数器RTC_CNT的计数值置0,然后每秒加1,RTC_CNT什么时候会溢出? RTC_CNT是一个32位寄存器,可存储的最大值为(232-1),这样的话就是在232秒之后溢出,大概换算为:
Time = 2^32/365/24/60/60大约等于136年
假如某个时刻读取到计数器的数值为X = 606024*2(2天),又知道计数器是在2016年1月1日的0时0分0秒置0的,那么根据计数器的这个相对时间数值,可以计算得到这个时刻是2016年1月3日的0时0分0秒了,而计数器会在(2016+136)年左右溢出.(如果我们穿越回到2016年1月1日,如果还在使用这个计数器提供事件的话就会出问题啦.).
定时器被置0的这个事件被称为计时元年,相对计时元年经过的秒数称为时间戳.
二、新建项目
使用STM32cubeMX建项目(我用的STM32C8T6芯片)
相关配置:
设置RCC
配置RTC(系统默认的日期和时间为2000年1月1日0时0分0秒,星期一,可以修改,我改为了2021年11月29日,星期一,21:40:0):
配置一个串口:
时钟树:
项目设置:
项目生成:
三、代码编写
main.c:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#