STM32F103 RTC配置
本节我们将介绍RTC
,实际上有关RTC
我们在学习S3C2440
的时候已经详细介绍过《Mini2440
裸机开发之RTC
》。
一、RTC
RTC
,英文全称Real Time Clock
,中文就是实时时钟,是一个可以为系统提供精确的时间基准的元器件,RTC
一般采用精度较高的晶振作为时钟源,有些RTC
为了在主电源掉电时还可以工作,需要外加电池供电。
1.1 概述
在断电情况下RTC
仍可以独立运行,只要芯片的外加电池一直供电,RTC
上的时间会一直走。
RTC
本质上是个独立的定时器。RTC
模块拥有一个连续计数的计数器。从定时器的角度来看,相对于通用定时器TIM
外设,它的功能十分简单,只有计时功能(也可以触发中断),但其高级之处也就在于掉电之后还可以正常运行。
两个32
位寄存器包含二进码十进数格式 (BCD
) 的秒、分钟、小时(12
或24
小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。系统可以自动将月份的天数补偿为28
、29
(闰年)、30
和31
天。
上电复位后,所有RTC
寄存器都会受到保护,以防止可能的非正常写访问。
无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC
不会停止工作。
1.2 特性
-
可编程的预分频系数:分频系数高为;
-
32
位的可编程计数器,可用于较长时间段的测量; -
2
个分离的时钟:用于APB1
接口的PCLK1
和RTC
时钟(RTC
时钟的频率必须小于PCLK1
时钟频率的四分之一以上); -
可以选择以下三种
RTC
的时钟源;HSE
时钟除以128
;LSE
振荡器时钟;LSI
振荡器时钟;
-
2
个独立的复位类型:APB1
接口由系统复位;RTC
核心(预分频器、闹钟、计数器和分频器)只能由后备域复位;
-
3
个专门的可屏蔽中断;- 闹钟中断,用来产生一个软件可编程的闹钟中断;
- 秒中断,用来产生一个可编程的周期性中断信号(长可达1秒);
- 溢出中断,指示内部可编程计数器溢出并回转为
0
的状态;
1.3 RTC
方框图

RTC
由两个主要部分组成。
- 第一部分(
APB1
接口):用来和APB1
总线相连,此单元还包含一组16
位寄存器,可通过APB1
总线对其进行读写操作。APB1
接口由APB1
总线时钟驱动,用来与APB1
总线连接; - 另一部分(
RTC
核心):由一组可编程计数器组成,分成两个主要模块;- 第一个模块是
RTC
的预分频模块(左下1):它可编程产生最长为1
秒的RTC
时间基准TR_CLK
。RTC
的预分频模块包含了一个20
位的可编程分频器(RTC
预分频器)。如果在RTC_CR
寄存器中设置了相应的允许位,则在每个实时时钟(RTC
)TR_CLK
周期中RTC
产生一个中断(秒中断); - 第二个模块是一个
32
位的可编程计数器(左下2):可被初始化为当前的系统时间;系统时间按TR_CLK
周期累加并与存储在RTC_ALR
寄存器中的可编程时间相比较,如果RTC_CR
控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。
- 第一个模块是
1.3.1 RTCCLK
选择
我们在《STM32F103
系统时钟配置》中介绍了STM32
的时钟框图;

RTCCLK
可以选择以下三种作为时钟源;
HSE
时钟除以128
;LSE
振荡器时钟;LSI
振荡器时钟;
使用HSE
分频时钟或者LSI
的时候,在主电源VDD
掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC
正常工作,所以RTC
一般都时钟低速外部时钟LSE
,频率为实时时钟模块中常用的32.768KHz
。
因为32768 = 2^15
,分频容易实现,所以被广泛应用到RTC
模块。在主电源VDD
有效的情况下(待机),RTC
还可以配置闹钟事件使STM32
退出待机模式。
1.3.2 具体流程
RTCCLK
经过RTC_DIV
预分频,RTC_PRL
设置预分频系数,然后得到TR_CLK
时钟信号,我们一般设置其周期为1s
,RTC_CNT
计数器计数,假如1970
设置为时间起点为0s
,通过当前时间的秒数计算得到当前的时间。
RTC_ALR
是设置闹钟时间,RTC_CNT
计数到RTC_ALR
就会产生计数中断;
RTC_Second
为秒中断,用于刷新时间;RTC_Overflow
是溢出中断;RTC Alarm
控制开关机。
1.3.3 RTC
复位过程
除了RTC_PRL
、RTC_ALR
、RTC_CNT
和RTC_DIV
寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。
RTC_PRL
、RTC_ALR
、RTC_CNT
和RTC_DIV
寄存器仅能通过备份域复位信号复位。
系统复位后,禁止访问后备寄存器和RCT
,防止对后卫区域(BKP
)的意外写操作。
1.3.4 读RTC
寄存器
RTC
内核完全独立于APB1
接口,软件通过APB1
接口对RTC
相关寄存器访问。但是相关寄存器只在RTC APB1
时钟进行重新同步的RTC
时钟的上升沿被更新。所以软件必须先等待寄存器同步标志位(RTC_CRL
的RSF
位)被硬件置1
才读。
1.3.5 配置RTC
寄存器
必须设置RTC_CRL
寄存器中的CNF
位,使RTC
进入配置模式后,才能写入RTC_PRL
、RTC_CNT
、RTC_ALR
寄存器。
另外,对RTC
任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR
寄存器中的RTOFF
状态位,判断RTC
寄存器是否处于更新中。仅当RTOFF
状态位是1
时,才可以写入RTC
寄存器。
二、RTC
相关寄存器
RTC
相关的寄存器主要有:
RTC
控制寄存器:RTC_CRH
,RTC_CRL
;RTC
预分频装载寄存器:RTC_PRLH
,RTC_PRLL
;RTC
预分频余数寄存器:RTC_DIVH
,RTC_DIVL
;RTC
计数器寄存器:RTC_CNTH
,RTC_CNTL
;RTC
闹钟寄存器:RTC_ALRH
,RTC_ALRL
。
2.1 RTC
控制寄存器
2.1.1 RTC_CRH

作用:配置3个专门的可屏蔽中断(溢出中断、闹钟中断、秒中断)使能。
注意:系统复位后所有的中断被屏蔽,因此可通过写RTC
寄存器来确保在初始化后没有挂起的中断请求。当外设正在完成前一次写操作时(标志位RTOFF=0
),不能对RTC_CRH
寄存器进行写操作。
2.1.2 RTC_CRL


一般用到该寄存器的3
,4
,5
位:
- 位
3
(RSF
):寄存器同步标志位,我们在修改控制寄存器RTC_CRH
/RTC_CRL
之前,必须先判断该位,是否已经同步了,如果没有则等待同步; - 位
4
(CNF
):配置标位,在软件修改RTC_CNT
/RTC_ALR
/RTC_PRL
的值的时候,必须先软件置位该位,以允许进入配置模式; - 位
5
(RTOFF
):RTC
操作位,该位由硬件操作,软件只读。通过该位可以判断上次对RTC
寄存器的操作是否完成,如果没有,我们必须等待上一次操作结束才能开始下一次,也就是判断RTOFF
位是否置位。
3
个位总结如下:
(1) 修改RTC_CRH
/RTC_CRL
寄存器,必须先判断RSF
位,确定已经同步;
(2) 修改RTC_CNT
/RTC_ALR
/RTC_PRL
的时候,必须先配置CNF
位进入配置模式,修改完之后,设置CNF
位为0
退出配置模式。
(3) 同时在对RTC
相关寄存器写操作之前,必须先判断RTOFF
位,确定上次对RTC
寄存器的操作是已经完成。
2.2 RTC
预分频装载寄存器
预分频装载寄存器用来保存RTC
预分频器的周期计数值。在修改这个寄存器的时候要先进入配置模式,即设置RTC_CRL
寄存器中的CNF
位,使RTC
进入配置模式。
我们使用外部32.768kHz
的晶振作为RTC
时钟的输入频率,那么就要设置这两个寄存器的值为32767
(7FFF
)以得到1s
的计数频率。
2.2.1 RTC_PRLH

2.2.2 RTC_PRLL

2.3 RTC
预分频余数寄存器
预分频余数寄存器用于获取比秒钟更准确的时钟。该寄存器的值是自减的,用于保存还需要多少时钟周期获取的一个秒信号。在一次秒钟更新后,由硬件重新加载,这两个寄存器和RTC_PRL
的各位是一样的。
在TR_CLK
的每个周期里,RTC
预分频器中计数器的值都会被重新设置为RTC_PRL
寄存器的值。用户可通过读取RTC_DIV
寄存器,以获得预分频计数器的当前值,而不停止分频计数器的工作,从而获得精确的时间测量。
此寄存器是只读寄存器,其值在RTC_PRL
或RTC_CNT
寄存器中的值发生改变后,由硬件重新装载。
2.3.1 RTC_DIVH

2.3.2 RTC_DIVL

2.4 RTC
计数器寄存器
存放计数器内的计数值,也就是用来记录时钟时间。
该寄存器由2
个16
位的寄存器组成RTC_CNTH
和RTC_CNTL
,总共32
位,当进行读操作时,直接返回计数器内的计数值(系统时间)。
在修改这个寄存器的时候要先进入配置模式,即设置RTC_CRL
寄存器中的CNF
位,使RTC
进入配置模式。
2.4.1 RTC_CNTH

2.4.2 RTC_CNTL

2.5 RTC
闹钟寄存器
当可编程计数器RTC_CNT
的值与RTC_ALR
中的32
位值相等时,即触发一个闹钟事件,并且产生RTC
闹钟中断。
在修改这个寄存器的时候要先进入配置模式,即设置RTC_CRL
寄存器中的CNF
位,使RTC
进入配置模式。
2.5.1 RTC_ALRH

2.5.2 RTC_ALRL

2.6 BKP
备份寄存器
备份寄存器是42
个16
位的寄存器。可用来存储84
个字节数据。
它们处在备份区域,当VDD
电源切断,仍然由VBAT
维持供电。
当系统在待机模式下被唤醒,或者系统复位或者电源复位,它们也不会复位。执行以下操作将使能对后备寄存器和RTC
访问:
- 设置寄存器
RCC_APB1ENR
的PWREN
和BKPEN
位,使能电源和后备时钟; - 设置寄存器
PWR_CR
的DBP
位,使能对RTC
和后备寄存器的访问;
2.6.1 备份数据寄存器(BKP_DRx
)
一般用BKP
来存储RTC
的校验值或者记录一些重要的数据;

2.6.2 备份域控制寄存器 (RCC_BDCR
)
备份域控制寄存器中(RCC_BDCR
)的LSEON
、LSEBYP
、RTCSEL
和RTCEN
位处于备份域。
因此,这些位在复位后处于写保护状态,只有在电源控制寄存器(PWR_CR
)中的DBP
位置1
后才能对这些位进行改动。

三、RTC
源码
3.1 RTC
初始化步骤
RTC
配置流程如下:
(1) 时钟使能以及取消写保护;
-
使能电源时钟和备份区域时钟:通过配置
RCC_APB1ENR
的位28
和位27
;-
位
28
(PWREN
):电源接口时钟使能; -
位
27
(BKPEN
):备份接口时钟使能;
-
-
取消备份区写保护:通过配置
PWR_CR
的DBP
位(位8
)为1
来使能对后备寄存器和RTC
的访问;
(2) RTC
时钟配置 (复位,取消复位,时钟源选择,使能)->该模块是在备份区域;
-
备份区域软复位,复位结束;
- 通过配置
RCC_BDCR
寄存器位16
为1
备份区域软复位; - 通过配置
RCC_BDCR
寄存器位16
为0
备份区域软复位结束;
- 通过配置
-
开启
LSE
;-
通过配置
RCC_BDCR
寄存器位0
使能外部低速振荡器; -
通过读取
RCC_BDCR
寄存器位1
等待外部低速振荡器就绪;
-
-
选择
RTC
时钟,并使能:通过配置RCC_BDCR
的位[9:8
]和位15
;-
位[
9:8
]:RTC
是时钟源选择,配置为01
选择LSE
作为RTC
时钟; -
位
15
:RTC
时钟使能;
-
(3) 等待上一次RTC
写操作完成:判断上一次RTC
操作是否完成,通过等待RTC_CRL
位5
(RTOFF=1
)实现;
亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。
日期 | 姓名 | 金额 |
---|---|---|
2023-09-06 | *源 | 19 |
2023-09-11 | *朝科 | 88 |
2023-09-21 | *号 | 5 |
2023-09-16 | *真 | 60 |
2023-10-26 | *通 | 9.9 |
2023-11-04 | *慎 | 0.66 |
2023-11-24 | *恩 | 0.01 |
2023-12-30 | I*B | 1 |
2024-01-28 | *兴 | 20 |
2024-02-01 | QYing | 20 |
2024-02-11 | *督 | 6 |
2024-02-18 | 一*x | 1 |
2024-02-20 | c*l | 18.88 |
2024-01-01 | *I | 5 |
2024-04-08 | *程 | 150 |
2024-04-18 | *超 | 20 |
2024-04-26 | .*V | 30 |
2024-05-08 | D*W | 5 |
2024-05-29 | *辉 | 20 |
2024-05-30 | *雄 | 10 |
2024-06-08 | *: | 10 |
2024-06-23 | 小狮子 | 666 |
2024-06-28 | *s | 6.66 |
2024-06-29 | *炼 | 1 |
2024-06-30 | *! | 1 |
2024-07-08 | *方 | 20 |
2024-07-18 | A*1 | 6.66 |
2024-07-31 | *北 | 12 |
2024-08-13 | *基 | 1 |
2024-08-23 | n*s | 2 |
2024-09-02 | *源 | 50 |
2024-09-04 | *J | 2 |
2024-09-06 | *强 | 8.8 |
2024-09-09 | *波 | 1 |
2024-09-10 | *口 | 1 |
2024-09-10 | *波 | 1 |
2024-09-12 | *波 | 10 |
2024-09-18 | *明 | 1.68 |
2024-09-26 | B*h | 10 |
2024-09-30 | 岁 | 10 |
2024-10-02 | M*i | 1 |
2024-10-14 | *朋 | 10 |
2024-10-22 | *海 | 10 |
2024-10-23 | *南 | 10 |
2024-10-26 | *节 | 6.66 |
2024-10-27 | *o | 5 |
2024-10-28 | W*F | 6.66 |
2024-10-29 | R*n | 6.66 |
2024-11-02 | *球 | 6 |
2024-11-021 | *鑫 | 6.66 |
2024-11-25 | *沙 | 5 |
2024-11-29 | C*n | 2.88 |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了