你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】RTC实时时钟,步骤超细详解,一文看懂RTC

[复制链接]
STMCU小助手 发布时间:2022-3-23 15:00
什么是RTC
, ]2 ^  ^/ }, i/ XRTC (Real Time Clock):实时时钟& E6 J/ R) l: ]1 v# t. k
9 |7 X+ L3 |( o
RTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。2 ?$ \% H% X% [  h% _

+ s) v6 m9 P4 g+ r% `7 \# \5 E %BVML)F}%LDLTBPWJQ%M.png
5 C. K4 N( J9 O+ j% }: u' ], D: f! S" ]6 [9 E. ]
在断电情况下 RTC仍可以独立运行 只要芯片的备用电源一直供电,RTC上的时间会一直走。* @- Q8 K' a! y
" n& L; C- z2 e6 k' _( S( K7 ~1 z
RTC实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断)。但其高级指出也就在于掉电之后还可以正常运行。7 o6 i& }8 v" Z+ x" V" W& [- }3 n: x3 f
7 ~% @6 I3 }& |. h* ~- p2 X
两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时( 12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。系统可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。% }* e" C4 _' C, ?8 ^

5 @% f& V: K1 f上电复位后,所有RTC寄存器都会受到保护,以防止可能的非正常写访问。
* ^5 _3 ~' g/ z* K( s
, |1 ]( j1 O$ h( ]0 R8 l' ^# H无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC使不会停止工作。# @$ z! m8 y2 J) w4 S

8 ?8 C4 O, |# L( ?, I! ], v$ }RCT特征:9 a; p6 [2 [' v
● 可编程的预分频系数:分频系数高为220。
, f' }; d, T1 H* Q$ @3 G● 32位的可编程计数器,可用于较长时间段的测量。
0 O1 ~5 l" U$ Q& `5 P1 N9 y● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟 频率的四分之一以上)。
/ w, F, g" d6 h' L/ V● 可以选择以下三种RTC的时钟源:
( A8 L5 O0 k8 r9 v; z7 L4 y$ Q     ● HSE时钟除以128;
  ^% ?! `0 j$ G- x% @2 K: N     ● LSE振荡器时钟;
8 A* _2 E" p2 ^* s     ● LSI振荡器时钟
  _5 r: P$ t2 \0 h, C; K0 @0 O! i* O9 B, M; ^
● 2个独立的复位类型:+ }, z0 T$ V* w7 Z0 P
     ● APB1接口由系统复位;7 Q* b' c: X. v# q; B
     ● RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位
- s: Q7 |& f" _/ z3 v" e' V9 U' `. w
. M8 R7 s; s5 P; N+ |● 3个专门的可屏蔽中断:
$ |+ ?, h& c6 o. v7 e! r     ● 1.闹钟中断,用来产生一个软件可编程的闹钟中断。5 p  l! k7 P! _

+ f. p2 H6 I/ M) {3 @# h- O     ● 2.秒中断,用来产生一个可编程的周期性中断信号(长可达1秒)。
1 B# b. }; B: {6 Q9 u7 v1 J& m6 l5 p/ E/ x6 v% ]
     ● 3.溢出中断,指示内部可编程计数器溢出并回转为0的状态。
: e& E4 z3 _% L; u' t. L$ x7 N) B) a; f, q1 V5 V+ u
RTC时钟源:( Z" O+ C& W5 _0 h# E+ K
三种不同的时钟源可被用来驱动系统时钟(SYSCLK):
5 u" |: f. Q, g. X# |● HSI振荡器时钟
+ y0 r8 u& @* [7 J1 z● HSE振荡器时钟2 M# w- L: o& G7 B/ M! Q1 e# ~0 E9 d! L6 Y+ C
● PLL时钟
/ }) h2 V* b3 g! w9 B* A9 h3 ^# b# C2 i' D, ]8 M# s' ^
这些设备有以下2种二级时钟源:
4 q- V2 e+ y# ~& M; s+ g" l' _- S* p- I) C3 ^4 q$ R: p- |2 N, [+ c
● 40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 RTC用于从停机/待机模式下自动唤醒系统。6 B6 X' L" T) e6 M1 Z
● 32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。
& ~9 Q+ |$ c/ x5 H) T, ^( p
& z, Y% j1 O2 i, pRTC原理框图
5 A2 M0 s% J  o7 ?) M+ |4 O& j+ Y1 _* l" |4 I# m
(CZ[3{TQHZWJK822Z@W$M0F.png 5 Y4 r/ A4 J) T3 a, r

9 Y1 Q& E2 G# N7 q- [RTC时钟的框图还是比较简单的,这里我们把他分成 两个部分:3 N+ \% Z" s5 p5 S
, s. z1 g7 R, D9 v1 k9 j% D
APB1 接口:用来和 APB1 总线相连。 此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总 线时钟驱动,用来与 APB1 总线连接。) u9 n+ v8 ^1 b" B* k
5 c. l# k4 x+ J, o$ C
通过APB1接口可以访问RTC的相关寄存器(预分频值,计数器值,闹钟值)。
2 N$ |& O: D5 J" k
) d* F6 B4 h& U8 ?RTC 核心接口:由一组可编程计数器组成,分成 两个主要模块 。
. O8 k  q6 p3 \* H1 i4 s! t1 N' m; |0 m' c0 J# [* [
VDT`KS@CNS$_D~2H83A$ERO.png & ^  `: J" B% y. k3 H) K
5 ~, w6 Q. A% _: v& `
第一个模块是 RTC 的 预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20 位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个 TR_CLK 周期中 RTC 产生一个中断(秒中断)。
) `1 N1 S8 g' `* d
( x' X8 H" O' A/ g& O( k* L7 N S%QX])YR}6FW1[L1X_}X_Y0.png
* }9 n$ ]3 f& h' y6 X; k! Y! z! @7 S9 D) i/ X
第二个模块是一个 32 位的可编程计数器 (RTC_CNT),可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记 录 4294967296 秒,约合 136 年左右,作为一般应用,这已经是足够了的。. ]; z/ v, K9 t* ]
( n' C" S: D) L9 x, t9 r7 n4 I
RTC具体流程:- i# g( d' M4 }9 K" r( Y
RTCCLK经过RTC_DIV预分频,RTC_PRL设置预分频系数,然后得到TR_CLK时钟信号,我们一般设置其周期为1s,RTC_CNT计数器计数,假如1970设置为时间起点为0s,通过当前时间的秒数计算得到当前的时间。RTC_ALR是设置闹钟时间,RTC_CNT计数到RTC_ALR就会产生计数中断,
" g( b: U# N. e, k2 e$ RRTC_Second为秒中断,用于刷新时间,, T8 n, n( k, B2 M. F
RTC_Overflow是溢出中断。$ G' I6 b" |* x; \/ H3 W' b
RTC Alarm 控制开关机
; R- v! X( f; uRTC时钟选择使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE,频率为实时时钟模块中常用的32.768KHz,因为32768 = 2^15,分频容易实现,所以被广泛应用到RTC模块.(在主电源VDD有效的情况下(待机),RTC还可以配置闹钟事件使STM32退出待机模式).
& ]% x5 _3 P$ P% b  h7 W/ V- H# P. e! |
RTC复位过程$ `$ |; ^* ?) m/ h
除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。6 k  k/ ^( f3 e. Y& C, N
RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。
% D7 ^" e( V* v3 u/ v
* x" K: B+ l- L7 j% m% \系统复位后,禁止访问后备寄存器和RCT,防止对后卫区域(BKP)的意外写操作* Q* q! G: S/ m# d/ E
8 s, W( S8 K, h& H
读RTC寄存器
& g4 m. h1 Y3 n" C7 B7 JRTC内核完全独立于APB1接口,软件通过APB1接口对RTC相关寄存器访问。但是相关寄存器只在RTC APB1时钟进行重新同步的RTC时钟的上升沿被更新。所以软件必须先等待寄存器同步标志位(RTC_CRL的RSF位)被硬件置1才读。/ I# x9 d, c4 U: x
5 F5 N- S3 o9 r- X/ b$ w3 _' D
配置RTC寄存器5 \  U* h5 o: G# t/ p
必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、6 `1 O$ G# G9 w4 Q3 n
RTC_CNT、RTC_ALR寄存器。6 ]1 f1 u  E6 l% t0 W1 l8 {" c8 [
  n+ _- ~: x9 S# N0 m; K
另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询
! r9 V6 t/ B% c: i* X& w6 rRTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是’1’
7 h# {) L6 ]3 V1 m2 p0 `, u! I. E时,才可以写入RTC寄存器。: [  I; D/ w& H; @7 e. T
9 s! Z1 @4 T; ]1 G! ?' N
RTC时钟源8 ~1 f4 B( o2 r6 u% |
RTC是一个独立的时钟源# T+ |( ?9 w, J2 p% }3 |
! x8 ]0 l9 d- ^6 Q1 |4 b; s, C
20200423222504785.png 2 C1 u: S& O8 T* u6 D! b3 q7 b. }
; }9 [3 w* R6 Y3 w
RTC寄存器% ?" P  N8 o' i) M. q2 X1 ]3 K6 M
RTC控制寄存器 (RTC_CRH, RTC_CRL)+ P  Z1 Z0 }9 w4 c
RTC预分频装载寄存器 (RTC_PRLH, RTC_PRLL)
5 ~# N/ V5 k9 wRTC预分频余数寄存器 (RTC_DIVH, RTC_DIVL)
3 m- [0 Y1 R  D& C* \RTC计数器寄存器 (RTC_CNTH, RTC_CNTL)
7 q5 ?3 [" ]* s6 fRTC闹钟寄存器 (RTC_ALRH ,RTC_ALRL)3 v6 s1 q5 {8 u% C  t( {% N% z
# P8 k; y& c' z, E2 [
RTC控制寄存器高位——RTC_CRH 寄存器
8 ~/ j: N3 c5 n8 h2 M# ?, r) t
6 t$ C; j5 ^4 v# P }J`K83NC3ZJM))1WIG`PDV8.png
% s* w8 o; I: p" \# C8 ^
( N& M+ A7 r7 S作用:配置3个专门的可屏蔽中断(溢出中断、闹钟中断、秒中断)使能。
8 X, s! e9 {) Z* M2 Y2 q" A2 c3 H0 k/ [2 X+ Q- b3 X7 t
注意:系统复位后所有的中断被屏蔽,因此可通过写RTC寄存器来, L5 \4 W1 M8 I6 S
确保在初始化后没有挂起的中断请求。当外设正在完成前一次写操作时(标志位RTOFF=0),不+ D7 F. a: x, P. d3 ?# ~; X
能对RTC_CRH寄存器进行写操作。
: Z; V. ]- l0 `7 W! ], u$ j  N3 ]6 i: y0 ~: Y! z
RTC控制寄存器低位——RTC_CRL 寄存器; `* n- Z/ T5 {# h4 O
2 a- W; U5 D4 w* q
~W2JSW`4CM_$V0OUGF_ZVVO.png
9 ~. e5 M8 _  q; I$ A$ e! N$ Q9 t8 x! N' D% `: {
一般用到该寄存器的 3,4,5位; K% T: U# z+ y; m) s5 d$ M! C" E) L
1.第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已经同步了,如果没有则等待同步' ~4 l, L* Z# |0 N1 Q7 O: q
2.第 4 位为配置标位,在软件修改 RTC_CNT/RTC_ALR/RTC_PRL 的值的时候,必须先软件置位该位,以允许进入配置模式! _1 C8 }7 Z& j; |. Q1 L4 S
3.第 5 位为 RTC 操作位,该位由硬件操作,软件只读。通过该位可以判断上次对 RTC 寄存器的操作是否完成,如果没有,我们必须等待上一次操作结束才能开始下一次,也就是判断RTOFF位是否置位。: V% r6 V) t2 ^, w+ U3 C
1 K8 V9 B* @" W% s; Y$ M5 C

3 T) q, s0 L: F& D' f三个位总结如下:8 w/ p3 }+ x4 x* p! Q+ G4 u4 v
① 修改CRH/CRL寄存器,必须先判断RSF位,确定已经同步。" e# r7 E4 P& S+ f; L" a
② 修改CNT,ALR,PRL的时候,必须先配置CNF位进入配置模式,修改完之后,设置CNF位为0退出配置模式7 i# d/ X. r! h) L. y
③ **同时在对RTC相关寄存器写操作之前,必须判断上一' V* L7 n. I1 m8 p  u/ k0 m8 t
2 y/ ^5 A  m: ^$ G7 o1 B5 X/ q$ F
OHPQAEI6Y1H8W0DECM_2.png 2 f! Q0 @- G/ F
) L/ K5 b! m+ W: v( z' E
RTC 预分频装载寄存器——(RTC_PRLH/RTC_PRLL) 寄存器
1 s$ m3 C8 D- C/ V作用:配置 RTC 时钟的分频数,
8 x" H; }, r. {1 V& z
/ o2 B6 a5 V" K- b比如我们使用外部 32.768K 的晶振作为时钟的输入频率,那么我们要设置这两个寄存器的值为 7FFFh(32767),就可获得周期为1秒钟的信号。# t+ r( o, c* Z8 ~
6 T% z6 m5 k; @. T$ k6 C" E
C066M$S_Q2K6TXFPPPG4_NB.png
  p' d0 e+ ?$ T1 d: k1 n- A  b0 ]: |3 ]- H1 r: L
RTC预分频器余数寄存器(RTC_DIVH、RTC_DIVL)+ ~- r  ~' K1 Y
作用: 和他的名字一样,获得余数,也就是获取更精确的计时,比如:0.1s ,0.01 s等, p* `" `7 }# r

! G* Q- u, {1 Z; |寄存器是只读寄存器,其值在RTC_PRL或RTC_CNT寄存器中的值发生改变后,由硬件重新装载。
0 G; q; |5 P+ L7 [) s( H
: P5 R! ~- D. p  F2 k. h( B 66FD1)VARVY_[ZGOY4GOWG3.png $ f* l! `& `2 c5 s8 }- R
; R' W9 e) Z% [
RTC 计数器寄存器——RTC_CNTX 寄存器

2 _4 v2 A6 c" U8 ~: b$ t: [作用:存放计数器内的计数值。也就是用来记录时钟时间4 b( N7 k* V; |. a# m! H

2 ]# I0 x3 A* P5 F, K# e该寄存器由 2 个 16 位的寄存器组成 RTC_CNTH 和 RTC_CNTL,总共 32 位,当进行读操作时,直接返回计数器内的计数值(系统时间)/ l) J& w" A( v" J% s: i  i7 y" \
3 E4 c* n7 q; Y0 t. \$ f/ Y
(5N(SIK7X6RN(HY@40S_2O3.png
; c0 Y/ g3 E2 Q7 ]; k6 B' T% `, M4 d% @5 I9 ~
RTC 计数器寄存器——RTC 闹钟寄存器(RTC_ALRH、RTC_ALRL)
+ R0 ]: T* s5 q# U1 @0 `作用: RTC时钟中断控制寄存器+ g! V; T7 K1 S% ~# p0 h+ A, I

2 ~' r/ u2 k- `& a: v% X该寄存器也是由 2 个 16 位的寄存器组成 RTC_ALRH 和 RTC_ALRL,也就是32位,当可编程计数器的值与RTC_ALR中的32位值相等时,即触发一个闹钟事件,并且产生RTC闹钟中断。
; }7 A( m6 x/ P/ H+ D# U" c
6 f! ^& @; D# q, G @AGLNS7O`D{M)H2NNF(6SHB.png 8 g$ q1 W- X& h6 i0 E& l
6 k$ X! B6 q% P0 B6 y
BKP备份寄存器
; Q- w  U' |8 Q5 C备份寄存器是42个16位的寄存器。可用来存储84个字节数据。
: z; ]+ J# D+ z! \8 l0 J它们处在备份区域,当VDD电源切断,仍然由VBAT维持供电。
: B; X# [" h- E9 R0 c
5 z) U, y1 F9 g当系统在待机模式下被唤醒,或者系统复位或者电源复位,它们也不会复位。
9 L6 V$ h2 ^: W8 n4 Q执行以下操作将使能对后备寄存器和RTC访问:  K0 N% N1 C5 `5 J) r/ w
设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备时钟。6 Y9 ]! q; ?$ M5 {6 w3 l; {
设置寄存器PWR_CR的DBP位,使能对RTC和后备寄存器的访问
# x5 B  \1 X0 |# u  r( G% i8 o7 m
! m- Z2 a. H6 U% s6 i- X; V" Z+ r
% d9 K' o: h1 d" A: g一般用 BKP 来存储 RTC 的校验值或者记录一些重要的数据,
! p0 `4 G$ T$ K, P/ x4 x- X- B6 ?+ A% W
@18S~}}JRPSV4JT~%2Q$K7N.png . Q, P0 |; k$ a5 Q9 S$ O$ ~

/ P) M. i4 i7 i# {- o5 L配置RTC寄存器:# [, U( ~8 P$ a. E6 X$ C) e! {
1.查询RTOFF位,知道RTOFF的值为1.. l+ P- |8 n# R: B) l, T

# K" |- v: T: L4 {: F" A2.置CNF值为1,进入配置模式。
% l% u7 W& ~6 t6 n* @' J
7 z5 o( F; ]# J6 m* W3.对一个或者多个RTC寄存器进行写操作。" N9 ~+ F+ f' w, ]- k6 J( m1 M. m

! C4 S6 |, ?+ a8 Z4.清除CNF标志位,退出配置模式。
9 Q/ j8 v2 P6 P1 B" p5 [0 z  O2 {+ g. `9 H( r5 G
5.查询RTOFF,直到RTOFF位变1,已确认写操作已经完成。
8 E4 J/ e  A+ q* E
. `. t5 N$ m9 S, P% x+ {, @" T仅当CNF标志位被清除时,写操作才能进行,这个操作至少需要3个RTCCLK周期。# Q/ \4 n0 C0 ]- X

- P/ S7 x0 G! b' I; A3 WRTC相关库函数  D6 A* O2 M2 z$ b. V' |
RTC时钟源和时钟操作函数:' T9 O5 z" h( f* G
  1. void RCC_RTCCLKConfig(uint32_t  CLKSource);//时钟源选择; o6 ~( @# J, l$ O; h' I
  2. void RCC_RTCCLKCmd(FunctionalState NewState)//时钟使能
复制代码

% `! V4 T: v! n8 O, d* _6 sRTC配置函数(预分频,计数值):
8 Q; e. e' Y0 L4 H" y) I7 E
  1. void RTC_SetPrescaler(uint32_t PrescalerValue);//预分频配置:PRLH/PRLL
    2 S0 j, M9 e, W  M. l% N
  2. void RTC_SetCounter(uint32_t CounterValue);//设置计数器值:CNTH/CNTL
    + [+ S3 k5 N0 `' C" j
  3. void RTC_SetAlarm(uint32_t AlarmValue);//闹钟设置:ALRH/ALRL
复制代码

' j0 l- K! t0 x6 mRTC中断设置函数:  C9 M* g1 X* x2 k! y
  1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//CRH
复制代码

* i# G3 E% R+ r" Q/ P0 `" X, HRTC配置函数:/ q6 \% z8 k6 U2 ?# l
  1. void RTC_EnterConfigMode(void);//允许RTC配置 :CRL位 CNF
    4 V% u0 F% @# i1 w
  2. void RTC_ExitConfigMode(void);//退出配置模式:CRL位 CNF
复制代码
! K1 N3 l# s, k0 L# u5 Q
RTC同步函数:. i' Q' d% s  y6 c, G
  1. void RTC_WaitForLastTask(void);//等待上次操作完成:CRL位RTOFF
    3 r, @0 z  J/ Q  T/ R
  2. void RTC_WaitForSynchro(void);//等待时钟同步:CRL位RSF
复制代码

% S: M! i& E) Y; tRTC相关状态位获取清除函数:
0 h  \0 s0 Z* v. [7 u
  1. FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);, Z7 s/ y) u2 b5 z3 |$ F8 Q0 a
  2. void RTC_ClearFlag(uint16_t RTC_FLAG);
    & l' D0 |4 v- B0 @4 Q
  3. ITStatus RTC_GetITStatus(uint16_t RTC_IT);: \# ^) @, c7 U& c7 u) k3 Y- c
  4. void RTC_ClearITPendingBit(uint16_t RTC_IT);
复制代码
1 z) m/ N% l1 L4 C- \
其他相关函数(BKP等)$ k& D4 o6 Q" J
  1. PWR_BackupAccessCmd();//BKP后备区域访问使能( r4 h3 n! u, n1 A
  2. RCC_APB1PeriphClockCmd();//使能PWR和BKP时钟
    ) ~* k: l7 H4 Y
  3. RCC_LSEConfig();//开启LSE,RTC选择LSE作为时钟源        
    + K; a( @, h& \+ D* W1 ^
  4. PWR_BackupAccessCmd();//BKP后备区域访问使能
    $ L6 Y* a( o7 w" O
  5. uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读BKP寄存器5 u% G/ s. \3 q. b- J5 S4 \% p
  6. void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//写BKP
复制代码
* M8 \4 [4 T$ R5 [1 U
配置RTC步骤
& v9 }+ s. D+ W①使能PWR和BKP时钟:9 G4 l! T2 C% w  r
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
复制代码
  ]; ~& W8 s! M# R0 h$ n
② 使能后备寄存器访问:
5 Y! b: s8 g; \6 c/ r9 [9 G0 D6 n& q7 c
  1. PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
复制代码

/ \' t4 t! H1 T1 ^4 C③复位备份区域,开启外部低速振荡器。
$ f- {: X2 o$ P9 N
  1. BKP_DeInit();//复位备份区域
复制代码
+ f% \0 u3 b& o* H+ V6 S; F, t
④ 配置RTC时钟源,使能RTC时钟:
8 C: l' @* E& w% Z7 K+ {4 S, {
  1. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟(RCC_RTCCLKSource_LSI 和 RCC_RTCCLKSource_HSE_Div128)# {* \* `* g% @  K5 O
  2. RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
复制代码

/ l. i9 W( _9 i1 |" B⑤ 设置RTC预分频系数:RTC_SetPrescaler();
+ H. w. u' W) V$ z7 ?
  1. RTC_EnterConfigMode();/// 允许配置        5 ]% T3 Z+ N4 g, C
  2. RTC_SetPrescaler(32767); //设置RTC预分频的值
    . [8 s! n$ }; h6 s5 N3 t. W- t3 l! A9 R
  3. RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
复制代码

8 ?: |& M: G6 {, Q. ^⑥ 设置时间:RTC_SetCounter();+ E% I1 n. K" e" C4 f
  1. RTC_EnterConfigMode();/// 允许配置1 t7 b$ [% K4 a6 ^9 e! N
  2. void RTC_SetCounter(uint32_t CounterValue);8 p0 D! K( I1 i/ Y! S/ x9 ^
  3. RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
复制代码
) o1 X2 e. s% H, N
⑦开启相关中断(可选):" H# W+ J* G" B  v( _
  1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
复制代码

7 b' Z! k. Q- z/ O⑧编写中断服务函数:- O( w- P4 t$ W9 ]1 a8 e6 Q
  1. RTC_IRQHandler();
复制代码
  y' b% x  V, b4 N! x9 L/ A0 K
⑨部分操作要等待写操作完成和同步。
7 D4 D0 F- s; ?7 W
  1.    RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
    $ ^- A; z( X% Q# p
  2.    RTC_WaitForSynchro();        //等待RTC寄存器同步
复制代码
2 q7 d$ O' t/ x
具体的代码,库函数写的太多了,我会用CubeMx配置下,用HAL库写一个例程,几十行就可以解决RTC,
* K( T8 k2 c$ u1 R2 n) k& ?; k2 w7 {  c- U
/ a; U& X8 T& \" w
& u4 b0 ?* l6 ^, D

& @9 g$ S" c* ^# z7 U
赞 收藏 评论0 发布时间:2022-3-23 15:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版