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

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

[复制链接]
STMCU小助手 发布时间:2022-3-23 15:00
什么是RTC) z/ d& ?3 ~- w! `8 ]! g
RTC (Real Time Clock):实时时钟
4 r* C0 f4 y6 W, {. m; t# j/ w3 T# y# n
RTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。
: B( W- M+ J1 ~4 `7 s# M2 x
- R$ u/ g9 S; m) w9 V5 X %BVML)F}%LDLTBPWJQ%M.png " I; s6 F, D2 }6 n) E5 q
4 \9 E0 m7 U9 x0 m7 v2 {
在断电情况下 RTC仍可以独立运行 只要芯片的备用电源一直供电,RTC上的时间会一直走。
& R6 P  |' E, W% {1 K
: \- R5 L  Y- aRTC实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断)。但其高级指出也就在于掉电之后还可以正常运行。
. N/ ?2 x$ s4 ]- F8 f6 d5 ~- q/ P5 }) y4 T7 r
两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时( 12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。系统可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。
* d1 ~* B" K2 H) K5 C- d8 D( J5 ?# `' \1 Z1 K( ^3 ^; i
上电复位后,所有RTC寄存器都会受到保护,以防止可能的非正常写访问。2 }/ T4 ]* G9 L: z$ c
& L. w' I7 G" a) J! n
无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC使不会停止工作。7 t% X% l" r+ X& H; l) I
' y6 ]3 h' t$ B8 r0 M
RCT特征:, |6 S! K* ^) ]
● 可编程的预分频系数:分频系数高为220。# {/ j3 i) l" ~. \- Q$ N( P% C/ N& ?
● 32位的可编程计数器,可用于较长时间段的测量。, ]# d1 z$ t2 D# Q5 ^6 G0 I. s4 h
● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟 频率的四分之一以上)。
, P% q) Z; y' f! T/ S0 S' [0 t: ]6 E● 可以选择以下三种RTC的时钟源:+ x0 N8 _( ?- d3 @! ?+ O
     ● HSE时钟除以128;
7 N) l- a- W  M/ R( O1 `- ?4 h     ● LSE振荡器时钟;
8 Z2 A- P% o6 m     ● LSI振荡器时钟0 D6 W" n, b6 |7 t: \. f

: w3 [( A# ]# r& L& H, Y" _● 2个独立的复位类型:/ o* B" j+ v6 c& C! Q
     ● APB1接口由系统复位;
1 B: I- J% D" K2 r1 v     ● RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位
0 h/ `6 K( `. {! n9 d
2 {1 y8 ]% L* c" w8 h/ ?+ v● 3个专门的可屏蔽中断:
5 m8 B. O/ [% |1 S5 |5 Y     ● 1.闹钟中断,用来产生一个软件可编程的闹钟中断。1 o4 o5 R0 \3 x! t/ q

  B' N" k( ^" h5 [     ● 2.秒中断,用来产生一个可编程的周期性中断信号(长可达1秒)。2 V1 x, t- S- M5 W; W% _7 D
% T1 M0 l& c$ k0 a
     ● 3.溢出中断,指示内部可编程计数器溢出并回转为0的状态。2 [" q, z% v; n3 ^# G

9 L$ S4 g- e7 R$ dRTC时钟源:3 @' Z; X! ~/ C) q" {
三种不同的时钟源可被用来驱动系统时钟(SYSCLK):
* T6 e7 ?) R( P● HSI振荡器时钟
8 m& t; W& R' m. a* T● HSE振荡器时钟  W! Y. T8 B8 m2 O9 `+ U
● PLL时钟1 ^" X9 J6 l1 k8 ~6 q4 p9 u
$ B1 H) b: u, V: x
这些设备有以下2种二级时钟源:$ S& T7 W0 l3 j" q( K: y7 v, |7 E

$ I/ b+ |: d; A6 w  s7 d  Z% ^' S● 40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 RTC用于从停机/待机模式下自动唤醒系统。
3 N) t0 t  H" ^● 32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。
+ B: d  c7 t+ _  ]7 l* J  |# j2 n1 ?- L; L: M& L$ t$ N% N
RTC原理框图& F* {3 {' ^$ s% h

; {* ]& G; {5 ~/ P# ?- c& ] (CZ[3{TQHZWJK822Z@W$M0F.png + p! [: y( R% F; `( i* }
6 X9 p) O- L; q7 m7 ~3 {( a
RTC时钟的框图还是比较简单的,这里我们把他分成 两个部分:
( A& T8 o9 x" \- H- k6 d' ]' x. f# k2 Z
APB1 接口:用来和 APB1 总线相连。 此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总 线时钟驱动,用来与 APB1 总线连接。6 d7 E" e+ e8 w! ~! h
( A. l0 Q" p2 U! p7 E1 b) X- k
通过APB1接口可以访问RTC的相关寄存器(预分频值,计数器值,闹钟值)。  q5 P" X% D4 L" c" v

/ e- `3 H% e/ t+ kRTC 核心接口:由一组可编程计数器组成,分成 两个主要模块 。
) D, Q: U+ @  K! g; t5 T. J2 F* `4 z9 f! n* e2 a' Y9 \8 b
VDT`KS@CNS$_D~2H83A$ERO.png
6 k# ^; O; L" I8 R+ _# F  x" Y
3 l' E4 x" u  I+ a6 C第一个模块是 RTC 的 预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20 位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个 TR_CLK 周期中 RTC 产生一个中断(秒中断)。
* s1 J) H0 s( u& v4 T6 s( ^9 ~1 o! m! D, [( k& {# K3 C- ?
S%QX])YR}6FW1[L1X_}X_Y0.png
: v$ V0 w- Q) j% T; V) q- A3 {2 \6 u( E# m) d
第二个模块是一个 32 位的可编程计数器 (RTC_CNT),可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记 录 4294967296 秒,约合 136 年左右,作为一般应用,这已经是足够了的。5 k2 X# s/ {$ E7 `; u0 C, e
0 ^" ]4 G- d8 ^0 F  [7 ~
RTC具体流程:# e0 g2 M( a$ k* q2 e7 w- Z, l
RTCCLK经过RTC_DIV预分频,RTC_PRL设置预分频系数,然后得到TR_CLK时钟信号,我们一般设置其周期为1s,RTC_CNT计数器计数,假如1970设置为时间起点为0s,通过当前时间的秒数计算得到当前的时间。RTC_ALR是设置闹钟时间,RTC_CNT计数到RTC_ALR就会产生计数中断,
4 n8 D  |) B& M  @7 D8 N) Q% xRTC_Second为秒中断,用于刷新时间,2 X  }. ^1 U7 @
RTC_Overflow是溢出中断。
9 w: n- h; E0 p, \8 kRTC Alarm 控制开关机
& R9 p8 c! f- VRTC时钟选择使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE,频率为实时时钟模块中常用的32.768KHz,因为32768 = 2^15,分频容易实现,所以被广泛应用到RTC模块.(在主电源VDD有效的情况下(待机),RTC还可以配置闹钟事件使STM32退出待机模式).: _+ t  L6 E! P. p( ?' S

" {1 `) w! {3 A  }; cRTC复位过程; `. X; M+ L. o" I" U
除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。
) L/ z% J; `+ }$ e; R& n1 H6 LRTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。
: V9 K0 I7 i  Z9 ]$ v9 s0 w8 b5 Y; _4 V3 P' N3 C
系统复位后,禁止访问后备寄存器和RCT,防止对后卫区域(BKP)的意外写操作' X' f# W# K3 P) {
0 R+ x/ d. l5 F  A4 B
读RTC寄存器, ?* L* D& y; w1 ]( {
RTC内核完全独立于APB1接口,软件通过APB1接口对RTC相关寄存器访问。但是相关寄存器只在RTC APB1时钟进行重新同步的RTC时钟的上升沿被更新。所以软件必须先等待寄存器同步标志位(RTC_CRL的RSF位)被硬件置1才读。
# e! L3 B) u$ C/ H' a5 t3 A# S
0 d4 q4 q# [4 F4 A  ?5 [配置RTC寄存器
# @( W, {3 c" m" L必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、8 |* d7 }8 I3 J. F( p& x' o
RTC_CNT、RTC_ALR寄存器。' f3 i% J. ~2 l' l0 T0 N$ G

- {- l9 W4 a+ y另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询7 j. \7 T8 g) B" ?' T  E
RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是’1’
  `8 {$ f4 ]% l时,才可以写入RTC寄存器。, y" H, l) ]# p0 k
, R9 L. ~. F3 m: W
RTC时钟源
0 d8 e( w/ [% m/ ]; IRTC是一个独立的时钟源
' Q% Y8 r: C% G6 z: M$ j
$ V. E0 ~) h$ M 20200423222504785.png 5 r( ^9 e9 n2 V, ?
$ U! I9 s: B. @% H7 ], O3 z$ g1 ?
RTC寄存器
0 _9 i8 o* v( j8 {  G+ dRTC控制寄存器 (RTC_CRH, RTC_CRL)  }9 }, D9 R+ _% g1 p
RTC预分频装载寄存器 (RTC_PRLH, RTC_PRLL)
) c9 K- U/ w! Q2 PRTC预分频余数寄存器 (RTC_DIVH, RTC_DIVL)8 M6 w, g, |0 ^* b* L
RTC计数器寄存器 (RTC_CNTH, RTC_CNTL)
6 c1 ]. K+ V( wRTC闹钟寄存器 (RTC_ALRH ,RTC_ALRL)
' ~  B3 s+ ?$ G, _
! M) x0 p) n, E, L# GRTC控制寄存器高位——RTC_CRH 寄存器
! s. q! P' O3 _. p  z3 X
# o2 f9 S4 G( N# m) ]8 b }J`K83NC3ZJM))1WIG`PDV8.png 0 k2 F) n: [6 d" M$ X& N
& `: s$ f: }7 Q7 o8 i) I$ P
作用:配置3个专门的可屏蔽中断(溢出中断、闹钟中断、秒中断)使能。- O9 \" @6 J9 V! m% ~* \) v, _

7 Z, S! r9 D' G; U( o% a8 b, q$ a注意:系统复位后所有的中断被屏蔽,因此可通过写RTC寄存器来2 w/ k# p; U9 l
确保在初始化后没有挂起的中断请求。当外设正在完成前一次写操作时(标志位RTOFF=0),不
+ f  H) r$ X) Y) Y能对RTC_CRH寄存器进行写操作。
; M3 H" v; [2 s! c" V: D" J$ x
! y" w; `8 V' E$ N  i. lRTC控制寄存器低位——RTC_CRL 寄存器
$ Y" r; ]8 V5 L: O4 B( ?- q0 h4 l) k( X% X
~W2JSW`4CM_$V0OUGF_ZVVO.png
0 {) d/ c4 H' h1 R5 t: f
, D4 G9 q4 C4 I! \# e- q8 o1 |一般用到该寄存器的 3,4,5位, s( |8 |3 M5 D6 ?/ @
1.第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已经同步了,如果没有则等待同步
0 i- c. h$ O7 V5 j: X7 p2.第 4 位为配置标位,在软件修改 RTC_CNT/RTC_ALR/RTC_PRL 的值的时候,必须先软件置位该位,以允许进入配置模式
, K5 q9 ~9 J- I$ |3.第 5 位为 RTC 操作位,该位由硬件操作,软件只读。通过该位可以判断上次对 RTC 寄存器的操作是否完成,如果没有,我们必须等待上一次操作结束才能开始下一次,也就是判断RTOFF位是否置位。
4 g4 w: M6 T1 _& x7 |
% G, j3 L+ r/ X9 U, m
% W0 e5 Q$ E: n0 {三个位总结如下:' ?5 d  h" m0 D$ z6 P; B
① 修改CRH/CRL寄存器,必须先判断RSF位,确定已经同步。' W' _* E: i8 \3 X- P+ {. `
② 修改CNT,ALR,PRL的时候,必须先配置CNF位进入配置模式,修改完之后,设置CNF位为0退出配置模式
  U' R" O: f! ]: ?③ **同时在对RTC相关寄存器写操作之前,必须判断上一
/ b* u" g! O; P7 }5 A: V$ X; @. }$ D5 f( w: s: l
OHPQAEI6Y1H8W0DECM_2.png 7 d- n% ]5 _+ X1 y% k6 [
4 X* j6 S2 ]6 B) }
RTC 预分频装载寄存器——(RTC_PRLH/RTC_PRLL) 寄存器
1 }) }& \" z) c; j4 |  M' t- ~作用:配置 RTC 时钟的分频数,6 J; F% [2 O! F7 h% @9 F3 v2 f
% e- H. K9 G* S7 l3 x, @
比如我们使用外部 32.768K 的晶振作为时钟的输入频率,那么我们要设置这两个寄存器的值为 7FFFh(32767),就可获得周期为1秒钟的信号。/ V+ Z8 a; [2 c9 Z, O( f* e

2 f5 O4 K9 ~$ p  f( w C066M$S_Q2K6TXFPPPG4_NB.png
2 K7 @. n# @4 M/ C; I. j) C8 b2 ~' E" B( B6 \5 c' ^, P
RTC预分频器余数寄存器(RTC_DIVH、RTC_DIVL)
4 C% d7 {' N6 G. P$ [; P作用: 和他的名字一样,获得余数,也就是获取更精确的计时,比如:0.1s ,0.01 s等
2 U' C: u  @7 X! b8 w- v; x' `: `0 L' t2 A' L1 w1 L5 a
寄存器是只读寄存器,其值在RTC_PRL或RTC_CNT寄存器中的值发生改变后,由硬件重新装载。( n9 L1 G" d9 m& s" y% ]- d# e2 Y

* X% K0 D) Y4 x0 k2 G! `' l 66FD1)VARVY_[ZGOY4GOWG3.png
9 `7 Q% L4 n  W- G9 i2 C" y* ?' b0 l, r2 q: o, j' i$ H
RTC 计数器寄存器——RTC_CNTX 寄存器
, ^" ?! @1 h' f6 i
作用:存放计数器内的计数值。也就是用来记录时钟时间8 s) \& u8 s5 x7 O! m& A! ^

- p2 @" |, u8 n. {/ I该寄存器由 2 个 16 位的寄存器组成 RTC_CNTH 和 RTC_CNTL,总共 32 位,当进行读操作时,直接返回计数器内的计数值(系统时间)7 p8 ^5 J: q. ^/ R- ?1 ^1 Z

/ H1 ~3 D: |& ~: \ (5N(SIK7X6RN(HY@40S_2O3.png
% u- N% n" |! R  {9 I! b0 G# X7 k1 A. `# ]. k+ N' Y6 g
RTC 计数器寄存器——RTC 闹钟寄存器(RTC_ALRH、RTC_ALRL). c1 ^2 F! \9 u' B! M% B+ D
作用: RTC时钟中断控制寄存器
4 y/ z6 j3 t2 t) D/ W" D5 K  w0 |! x  Q8 o! S5 S: w! ^
该寄存器也是由 2 个 16 位的寄存器组成 RTC_ALRH 和 RTC_ALRL,也就是32位,当可编程计数器的值与RTC_ALR中的32位值相等时,即触发一个闹钟事件,并且产生RTC闹钟中断。
' K" B: D; p% o! \: q, L" n' M- V! [% p9 T4 S; i  i
@AGLNS7O`D{M)H2NNF(6SHB.png 5 a/ E; M: V  \
# W7 _+ _+ t) M: A7 [( b5 w! o
BKP备份寄存器
% v4 E+ |' V" f0 X备份寄存器是42个16位的寄存器。可用来存储84个字节数据。
/ W$ w) O" c: [' M- v+ r! p它们处在备份区域,当VDD电源切断,仍然由VBAT维持供电。
$ x; D9 k+ H# E9 ~2 m) C' l6 v5 u6 O9 N! O# {, b% K; Y
当系统在待机模式下被唤醒,或者系统复位或者电源复位,它们也不会复位。2 G( z, I. H- k- d, V  O
执行以下操作将使能对后备寄存器和RTC访问:3 }; F$ b  [7 f3 n2 q, \% K
设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备时钟。* c# Z- y+ x# |3 R: B( i2 n0 E
设置寄存器PWR_CR的DBP位,使能对RTC和后备寄存器的访问* P% e, C$ T( b( ^2 B' F

% \3 k& \' t* K- m4 @1 c6 l, Q9 F! y1 X6 p9 y; ~- f0 d+ |( O9 Z
一般用 BKP 来存储 RTC 的校验值或者记录一些重要的数据,8 \) B% N# {5 ~7 A& R# h, d. W4 m" p" p

4 C, S2 }# z) d5 P) v @18S~}}JRPSV4JT~%2Q$K7N.png
/ m0 H3 p/ i0 c5 l. K0 {  N
' t, q9 P: |/ M5 _" v/ u配置RTC寄存器:" N  t6 r- H5 a$ M
1.查询RTOFF位,知道RTOFF的值为1.- b" L) N+ y) B
7 s) M# s% ~0 v3 B
2.置CNF值为1,进入配置模式。+ H) p0 u! ]9 y8 w

1 t7 G- E8 Y+ S3.对一个或者多个RTC寄存器进行写操作。
8 g. h0 F% I8 q9 A1 Y2 q* {$ q& }1 I
4.清除CNF标志位,退出配置模式。
# B, v! H2 v! R! Q$ z) ]& n7 ]3 o" |' G0 I  I. o
5.查询RTOFF,直到RTOFF位变1,已确认写操作已经完成。9 w8 y7 E- D* G3 I0 n

! |' T; U. P6 W1 w4 p+ E3 R仅当CNF标志位被清除时,写操作才能进行,这个操作至少需要3个RTCCLK周期。2 P  t0 S; h/ X  S/ ?( t

5 n0 U1 r" {+ u  h* _RTC相关库函数
8 \. ?* N- L  R! l  ?) D1 Z* lRTC时钟源和时钟操作函数:
/ d1 \; I0 Q8 s9 N
  1. void RCC_RTCCLKConfig(uint32_t  CLKSource);//时钟源选择8 }4 }8 r# n$ q9 K
  2. void RCC_RTCCLKCmd(FunctionalState NewState)//时钟使能
复制代码
, H3 a+ J2 K# Z( g1 J* I
RTC配置函数(预分频,计数值):9 g4 _& x4 j5 Q5 J# D5 ]
  1. void RTC_SetPrescaler(uint32_t PrescalerValue);//预分频配置:PRLH/PRLL* b7 e3 A8 H2 z  a
  2. void RTC_SetCounter(uint32_t CounterValue);//设置计数器值:CNTH/CNTL
    " W- ^( Y- {8 ]
  3. void RTC_SetAlarm(uint32_t AlarmValue);//闹钟设置:ALRH/ALRL
复制代码
+ i9 o8 O9 S) t. m. k3 [( `. O
RTC中断设置函数:1 `$ r% a& O( ^6 B
  1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//CRH
复制代码
: g/ n/ j3 V# b) i: y& Y1 ~" j
RTC配置函数:: T, w! f3 N4 g7 \/ o: ~
  1. void RTC_EnterConfigMode(void);//允许RTC配置 :CRL位 CNF& c% d& h3 j9 X3 ~$ |
  2. void RTC_ExitConfigMode(void);//退出配置模式:CRL位 CNF
复制代码

# V5 a' `/ k2 X& _' KRTC同步函数:! s) B( |" D# Y, S, D% J5 \
  1. void RTC_WaitForLastTask(void);//等待上次操作完成:CRL位RTOFF/ t. z! b+ M3 I- Q! a
  2. void RTC_WaitForSynchro(void);//等待时钟同步:CRL位RSF
复制代码

3 G; Y% d- e& L$ JRTC相关状态位获取清除函数:4 v4 l3 e1 M! l
  1. FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);
    : T5 e& W) f% P' \" `- P' p7 C
  2. void RTC_ClearFlag(uint16_t RTC_FLAG);
    9 |- T2 s( q* C. j. U8 R" O( l- k
  3. ITStatus RTC_GetITStatus(uint16_t RTC_IT);% J. A/ H; v# |) B0 O% w9 X
  4. void RTC_ClearITPendingBit(uint16_t RTC_IT);
复制代码

# m7 X: T  h% O1 ]+ _其他相关函数(BKP等)* p$ C# x, i0 @; |& ?
  1. PWR_BackupAccessCmd();//BKP后备区域访问使能
    6 m- t* Y. P/ p: f# u
  2. RCC_APB1PeriphClockCmd();//使能PWR和BKP时钟
    * r/ Q1 d& J! ]0 n
  3. RCC_LSEConfig();//开启LSE,RTC选择LSE作为时钟源        
    8 I$ s# k7 |1 Y/ h# j
  4. PWR_BackupAccessCmd();//BKP后备区域访问使能
    & W* c: s6 e5 M
  5. uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读BKP寄存器& ]+ v3 m5 E* D: z9 _8 K
  6. void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//写BKP
复制代码

- N; X% p. B# L" I$ v配置RTC步骤# a0 V% S  t! ~" \$ {
①使能PWR和BKP时钟:. v7 `5 o( X! S9 `* m' O! m# l- C
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
复制代码
. V" n9 d- C, X% \$ S$ t% @$ w+ g
② 使能后备寄存器访问:
+ S$ P; B* S" G. w1 t5 L# {8 \
  1. PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
复制代码

5 p2 N" {! P5 Z. x0 D9 l③复位备份区域,开启外部低速振荡器。
7 _: ~0 o! |0 S. n1 k7 ~
  1. BKP_DeInit();//复位备份区域
复制代码
4 V7 H' @3 g. _- @0 ]$ y
④ 配置RTC时钟源,使能RTC时钟:. x# J3 g6 A6 S" t' B9 C: j* y4 b6 J0 Q
  1. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟(RCC_RTCCLKSource_LSI 和 RCC_RTCCLKSource_HSE_Div128)
    # V) s" t# F, q$ D  e+ q
  2. RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
复制代码
2 i7 c% D  j9 v- x6 {/ Z* X" D% M
⑤ 设置RTC预分频系数:RTC_SetPrescaler();+ V, F" l, u- W' k# G3 i
  1. RTC_EnterConfigMode();/// 允许配置        3 S' Z( G) @# V, V
  2. RTC_SetPrescaler(32767); //设置RTC预分频的值
    7 L' Z  U0 A/ T# f* b
  3. RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
复制代码
/ O) z* F7 o1 E/ Y
⑥ 设置时间:RTC_SetCounter();
# P/ ?: }3 }$ T9 [1 H' V/ s; k
  1. RTC_EnterConfigMode();/// 允许配置
    + G1 b$ n7 z; @1 O1 W2 m
  2. void RTC_SetCounter(uint32_t CounterValue);
    ( j6 d/ N% J, D5 l; k
  3. RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
复制代码
# |2 O8 W* Y4 [- @% I
⑦开启相关中断(可选):
& B# G7 F# e) R
  1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
复制代码
& {3 s8 r! t( d0 G8 p6 a9 O; z
⑧编写中断服务函数:7 ~/ b8 S8 G& w" s8 Q1 H& c7 y
  1. RTC_IRQHandler();
复制代码

4 @1 s8 }0 q+ n  Q/ m' U* M' e6 `⑨部分操作要等待写操作完成和同步。
. e& \% b* E$ z
  1.    RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
    3 j  w  q$ s. e# w, [0 I
  2.    RTC_WaitForSynchro();        //等待RTC寄存器同步
复制代码

$ u  @8 A+ m2 G$ H5 b) ?具体的代码,库函数写的太多了,我会用CubeMx配置下,用HAL库写一个例程,几十行就可以解决RTC,  }* j$ K. r  y
" V) K) \3 {, D
4 z3 d  X% [; V

, g) r/ b0 b& G/ R" X* m- {6 u3 Q9 Z+ w
收藏 评论0 发布时间:2022-3-23 15:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版