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

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

[复制链接]
STMCU小助手 发布时间:2022-3-23 15:00
什么是RTC2 f9 |! D6 i2 f+ B' e% p
RTC (Real Time Clock):实时时钟
; D$ i: l9 |4 m, X( c) G
7 s/ `+ q0 V2 ?7 @1 d( z, r3 c2 KRTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。
) f/ Q! P8 F2 r$ C/ i: V  L4 P' b: L( ?' H4 B0 O
%BVML)F}%LDLTBPWJQ%M.png 9 D; a( e% q5 W7 i

, i2 N7 ?  x* o  g在断电情况下 RTC仍可以独立运行 只要芯片的备用电源一直供电,RTC上的时间会一直走。6 I) A; p, U! E# N, z5 N7 k

; n% H7 {- J+ s& C, o9 eRTC实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断)。但其高级指出也就在于掉电之后还可以正常运行。' A6 [2 o7 w2 T
  Y, _" m' Q8 d
两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时( 12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。系统可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。
: [" o# x! ~# K5 F* D% r3 F( i
% j) C3 W! V' n) c. b0 W- E上电复位后,所有RTC寄存器都会受到保护,以防止可能的非正常写访问。/ U, {6 E4 Y4 `* a* W' \% N
* P8 o6 _% _9 f3 \4 S& N5 s' J
无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC使不会停止工作。
. n9 P3 l( n9 x" l; ]0 Z
7 t, }8 g7 V8 s7 j5 s+ ^) n, PRCT特征:
' ~: \- d* A0 S: W● 可编程的预分频系数:分频系数高为220。7 D; ^6 p) g1 ^* c- T/ x
● 32位的可编程计数器,可用于较长时间段的测量。. k- G# i! V2 U! v
● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟 频率的四分之一以上)。
. H( x/ X" A3 e7 @" r# P  T+ Q● 可以选择以下三种RTC的时钟源:
2 C$ H6 b+ ]1 G8 N& N& B     ● HSE时钟除以128;
9 p, |. {* i5 B4 z$ `9 p/ s. |     ● LSE振荡器时钟;
8 U& f+ X9 p, d9 U3 ~& o" {& o- |     ● LSI振荡器时钟
" p4 T9 W6 C! {& R0 R! \; m* j$ u% \8 F! z1 t
● 2个独立的复位类型:
: b# H& y# x) ?+ Y     ● APB1接口由系统复位;6 R8 P8 G2 X5 X7 J
     ● RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位0 b6 R4 E2 D6 q( v0 j% p: k6 M4 l
: w8 N  h9 W# S  C8 o) s
● 3个专门的可屏蔽中断:
* B) ^) |" Z# e. i3 ]     ● 1.闹钟中断,用来产生一个软件可编程的闹钟中断。
: D6 Y; u7 S- u& M3 a4 f! v6 M* k7 E) R6 w, o, I- Y
     ● 2.秒中断,用来产生一个可编程的周期性中断信号(长可达1秒)。
0 ~  g  P# N1 R- g/ D; L+ ^# m5 O2 ^! B+ E: G! g
     ● 3.溢出中断,指示内部可编程计数器溢出并回转为0的状态。
$ O; a  G  |/ I$ f
4 z8 ~1 p' }4 p) \8 z$ b# Q/ RRTC时钟源:& a$ f7 q& T" b# X% c% o
三种不同的时钟源可被用来驱动系统时钟(SYSCLK):6 U9 y! z8 V; M4 @
● HSI振荡器时钟( `- h' m/ T* z4 y" ?6 t& ~0 @* ^- I- U
● HSE振荡器时钟
" }3 d# n" g7 n0 F! ~● PLL时钟
% g0 N( a1 U# n1 ]
8 T9 F- q& ^7 z+ K; n0 k3 K! i7 I这些设备有以下2种二级时钟源:
+ S+ c: ]# G% G, X! S0 g+ H" W  i5 W6 S* ?) a
● 40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 RTC用于从停机/待机模式下自动唤醒系统。
" i; z1 _) v4 M  J, e" Y● 32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。# i$ P9 a0 H* ?! r4 H; B- _. ~

; [- G6 ]9 x  P- h+ PRTC原理框图
; g) W( X' C* X# ]9 _  V. ~- o) h4 [1 F5 D) p9 w
(CZ[3{TQHZWJK822Z@W$M0F.png 7 {2 U% `1 `" B, I
$ T5 Q6 v2 ~7 _5 Q
RTC时钟的框图还是比较简单的,这里我们把他分成 两个部分:% ^) _4 b4 G; x9 t; K/ C

5 ^: {# l9 o( d" \6 eAPB1 接口:用来和 APB1 总线相连。 此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总 线时钟驱动,用来与 APB1 总线连接。
3 I# |: W# U2 ^$ i0 i- q0 ^9 n% l) O4 y$ S1 c" [8 H0 h) `/ L' c
通过APB1接口可以访问RTC的相关寄存器(预分频值,计数器值,闹钟值)。8 r! G- O, A6 H
$ P/ M% b1 b) r: ]* }
RTC 核心接口:由一组可编程计数器组成,分成 两个主要模块 。3 W# {7 \( C4 F; a+ n/ ]% F

' N  K' F& h8 P9 w* Y VDT`KS@CNS$_D~2H83A$ERO.png
) H: Z3 u5 u; m$ m4 i& X" d3 r7 ?/ R* I9 z
第一个模块是 RTC 的 预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20 位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个 TR_CLK 周期中 RTC 产生一个中断(秒中断)。
6 M$ @2 R- V+ G( L& g+ D9 [( O: D1 `& E/ J
S%QX])YR}6FW1[L1X_}X_Y0.png
, L% k4 V" @1 s& t% {' _3 J
$ Y% G8 f5 n2 o' |4 R第二个模块是一个 32 位的可编程计数器 (RTC_CNT),可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记 录 4294967296 秒,约合 136 年左右,作为一般应用,这已经是足够了的。; z. i% l6 q4 {: |! _' `# x1 d: \
8 b3 V2 C' M  |5 u4 b) O
RTC具体流程:
1 D0 s; G1 G; [8 j1 G* P* RRTCCLK经过RTC_DIV预分频,RTC_PRL设置预分频系数,然后得到TR_CLK时钟信号,我们一般设置其周期为1s,RTC_CNT计数器计数,假如1970设置为时间起点为0s,通过当前时间的秒数计算得到当前的时间。RTC_ALR是设置闹钟时间,RTC_CNT计数到RTC_ALR就会产生计数中断,  l' ^. u$ F. P/ t
RTC_Second为秒中断,用于刷新时间,
/ j5 \7 E8 X; F1 E$ S+ E6 DRTC_Overflow是溢出中断。
/ P( |) |6 N" L2 SRTC Alarm 控制开关机8 S9 b1 m' g. V4 l+ Z& }" x
RTC时钟选择使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE,频率为实时时钟模块中常用的32.768KHz,因为32768 = 2^15,分频容易实现,所以被广泛应用到RTC模块.(在主电源VDD有效的情况下(待机),RTC还可以配置闹钟事件使STM32退出待机模式).
; y1 t+ [/ [. Z+ j, y; H
- G3 R* }7 L' LRTC复位过程
# }+ Z( O* Y% v/ _# e( a8 [6 u1 _除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。
1 {  J3 ?' |$ B# j+ V) G. r+ rRTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。
( M5 M) B  K5 M+ m4 B* ^6 Q# g  |4 r; n
系统复位后,禁止访问后备寄存器和RCT,防止对后卫区域(BKP)的意外写操作
% s' z9 M; l6 W/ u) S6 v8 I1 E: V1 B& j. B( P- n4 @) i
读RTC寄存器
$ d9 c, o8 S, A& ~) K  KRTC内核完全独立于APB1接口,软件通过APB1接口对RTC相关寄存器访问。但是相关寄存器只在RTC APB1时钟进行重新同步的RTC时钟的上升沿被更新。所以软件必须先等待寄存器同步标志位(RTC_CRL的RSF位)被硬件置1才读。# g# ~$ ]6 A, p' u2 r2 Y

* D! V6 |* g3 h  Q) {  }配置RTC寄存器" z8 g$ F# L* v4 z1 _% I
必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、$ o& U$ B. K4 [1 y0 U" Q
RTC_CNT、RTC_ALR寄存器。
5 ]3 L" w+ n- ?4 c7 Y) |( }- J7 V
* {; l2 f7 d" x% z+ `! Y+ A另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询
  \' S) ]2 G. Z- u; tRTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是’1’; @+ Q0 L/ f; ^
时,才可以写入RTC寄存器。  t% _! q0 Q4 b/ y/ O/ s  v
3 C  d& w( R7 ~* i, H
RTC时钟源
% I; ?7 Y! I# B: P' a2 c7 S9 X1 R" [RTC是一个独立的时钟源* n# ?8 N, M+ k  ~+ m' g3 I+ F
  b; |$ ^7 k/ r+ n
20200423222504785.png " d& K" x( ?8 t! ^! x* Z

, d' k' v6 {) s. {2 n. [8 [" _RTC寄存器
' K9 X! B4 b$ R3 S$ ~  J4 u4 {& @RTC控制寄存器 (RTC_CRH, RTC_CRL)
( n, H6 W, X& e% f2 h) F% cRTC预分频装载寄存器 (RTC_PRLH, RTC_PRLL)
) A0 x' v* B' L, ]+ }' Q& t! oRTC预分频余数寄存器 (RTC_DIVH, RTC_DIVL)& C* `# y6 g* g- j9 y& c! L0 R
RTC计数器寄存器 (RTC_CNTH, RTC_CNTL)
$ K  H2 M2 ^$ ?1 VRTC闹钟寄存器 (RTC_ALRH ,RTC_ALRL)
( m# z1 h( J: B% |
6 }* w! g% R! s- o7 A7 e7 CRTC控制寄存器高位——RTC_CRH 寄存器
( \0 U6 K# w; x) i. e7 p2 b, p' g' t, Z
}J`K83NC3ZJM))1WIG`PDV8.png ( c9 z1 k# o0 g$ D3 A
2 Q" \. f1 ~6 F% r4 e
作用:配置3个专门的可屏蔽中断(溢出中断、闹钟中断、秒中断)使能。/ V9 x3 f4 _) G8 _

, Y+ Z2 w" @/ y0 f" C注意:系统复位后所有的中断被屏蔽,因此可通过写RTC寄存器来
/ O$ q( o3 o+ ~确保在初始化后没有挂起的中断请求。当外设正在完成前一次写操作时(标志位RTOFF=0),不$ p0 n* f1 c0 ~! s: b
能对RTC_CRH寄存器进行写操作。
2 z% c; e* r3 ^$ E# H/ x* \  I4 r9 _6 M7 k
RTC控制寄存器低位——RTC_CRL 寄存器1 [- M9 o) `% r% p$ |
+ Q# ]- g" U3 B8 J
~W2JSW`4CM_$V0OUGF_ZVVO.png $ i" U: A# a9 i3 Q# x# \' ]) l5 d$ e

1 o% z5 K/ t% B  M' x! N9 C" o一般用到该寄存器的 3,4,5位2 v1 E" L; K$ C9 r8 h' N
1.第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已经同步了,如果没有则等待同步8 F* e0 J. _! r% t6 S9 c. N
2.第 4 位为配置标位,在软件修改 RTC_CNT/RTC_ALR/RTC_PRL 的值的时候,必须先软件置位该位,以允许进入配置模式
( s! }8 l+ b/ I6 |0 v. q/ F8 ~3 ~8 S3.第 5 位为 RTC 操作位,该位由硬件操作,软件只读。通过该位可以判断上次对 RTC 寄存器的操作是否完成,如果没有,我们必须等待上一次操作结束才能开始下一次,也就是判断RTOFF位是否置位。
; X  r6 Y6 K: h+ ?* W5 V* l2 r; F. J

+ t3 b: y* z+ f3 Q三个位总结如下:2 i6 O; H7 `8 M2 K6 [- t
① 修改CRH/CRL寄存器,必须先判断RSF位,确定已经同步。
( Q5 ~" Q( t' {, y/ M" n+ w, C9 }② 修改CNT,ALR,PRL的时候,必须先配置CNF位进入配置模式,修改完之后,设置CNF位为0退出配置模式2 S8 H1 l$ i  t' G/ G, |6 }' U0 `
③ **同时在对RTC相关寄存器写操作之前,必须判断上一
- V+ i. o  J# Y/ y. j  @1 M$ Q& T% m9 M7 @
OHPQAEI6Y1H8W0DECM_2.png
7 G% S7 w. P, t5 V
! {2 T5 W# q' A0 W' n6 J! kRTC 预分频装载寄存器——(RTC_PRLH/RTC_PRLL) 寄存器
& k" Y, U$ Z; p2 R1 L作用:配置 RTC 时钟的分频数,
# J% E2 l2 m% H" L. e1 \& n% ?3 ~! u" ?2 [
比如我们使用外部 32.768K 的晶振作为时钟的输入频率,那么我们要设置这两个寄存器的值为 7FFFh(32767),就可获得周期为1秒钟的信号。
. s2 [6 a  y8 R* m# I
' t2 d6 E$ M+ q0 d' X5 n C066M$S_Q2K6TXFPPPG4_NB.png 8 f& o- g. u; k) B  @8 c& X" m+ p

) E. m- ~( ~% M) c% t# k) C# a8 eRTC预分频器余数寄存器(RTC_DIVH、RTC_DIVL)
% Z0 i. S- q) W0 l作用: 和他的名字一样,获得余数,也就是获取更精确的计时,比如:0.1s ,0.01 s等
8 F# x& l) w4 x0 h3 p: H. [' t! C( L# {7 _4 [* E
寄存器是只读寄存器,其值在RTC_PRL或RTC_CNT寄存器中的值发生改变后,由硬件重新装载。! B, D2 I/ Q& q0 J6 j

& U& V7 p  Q1 N( N5 b$ \ 66FD1)VARVY_[ZGOY4GOWG3.png ; V- y# h+ v$ }4 q& p. y

4 B- W8 |9 X4 v* L1 tRTC 计数器寄存器——RTC_CNTX 寄存器
6 H( P4 g1 z2 V0 K5 i' e8 b
作用:存放计数器内的计数值。也就是用来记录时钟时间
8 k6 I1 L+ J, x7 w2 {
2 t/ G8 ?' K( C0 U该寄存器由 2 个 16 位的寄存器组成 RTC_CNTH 和 RTC_CNTL,总共 32 位,当进行读操作时,直接返回计数器内的计数值(系统时间): k! h/ n$ h, h( |9 ^
' q: [# y7 L) B9 J
(5N(SIK7X6RN(HY@40S_2O3.png 5 r8 S6 x: g' U, K  \* O
/ F8 i# u! t8 \. ?6 I( `
RTC 计数器寄存器——RTC 闹钟寄存器(RTC_ALRH、RTC_ALRL): S6 z9 ~3 s# V0 E# |# P- R
作用: RTC时钟中断控制寄存器5 f& q( p, w3 l7 D6 M( ^! a
- Y* h+ b. S) J0 S
该寄存器也是由 2 个 16 位的寄存器组成 RTC_ALRH 和 RTC_ALRL,也就是32位,当可编程计数器的值与RTC_ALR中的32位值相等时,即触发一个闹钟事件,并且产生RTC闹钟中断。
- H5 E3 ?1 i/ W( o7 H! Y" ?! h8 k1 P6 N5 K% r! r
@AGLNS7O`D{M)H2NNF(6SHB.png
, n& B* w) y2 o0 n8 D- F# t8 |! m. c3 m/ P( A# t( d: F1 y8 {
BKP备份寄存器
: O( j# ]' i+ y  D* O) g+ C备份寄存器是42个16位的寄存器。可用来存储84个字节数据。
, c5 l2 M6 W4 ~它们处在备份区域,当VDD电源切断,仍然由VBAT维持供电。
* O+ w  V9 ~2 ^" \" _
2 e$ s5 E  H1 y% w当系统在待机模式下被唤醒,或者系统复位或者电源复位,它们也不会复位。, T2 |: `) v  O$ [! Q  U" y' |
执行以下操作将使能对后备寄存器和RTC访问:
5 u! m+ U- d. `" {& s& z设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备时钟。
9 R+ V' j( K' i设置寄存器PWR_CR的DBP位,使能对RTC和后备寄存器的访问# h; t( Y8 T1 H( L9 Z6 t' k
" M  W7 X7 t" m0 B4 t

$ S3 U2 ]; d& q一般用 BKP 来存储 RTC 的校验值或者记录一些重要的数据,
+ ~& X' I$ I! c, @* {
9 y3 A0 @; c5 s' u( E8 p @18S~}}JRPSV4JT~%2Q$K7N.png % h$ n1 N0 h+ e+ r; P
6 t+ ?1 w2 t( N) j
配置RTC寄存器:# k/ s8 @  b) H  ^% j& M9 u
1.查询RTOFF位,知道RTOFF的值为1.
! ?: c$ R/ T* x4 `2 S- }$ B2 [- }8 f- b' n$ P2 d5 L$ r- s: v5 l/ k' `
2.置CNF值为1,进入配置模式。
' h/ |+ I1 e: w& E$ a: i1 W1 A3 l" u5 o6 T- B
3.对一个或者多个RTC寄存器进行写操作。
; q; w$ ?  X; _4 t6 s# G% \0 |. @1 ~* T8 d% j; ?2 \& O( }5 v
4.清除CNF标志位,退出配置模式。4 E* e2 l, o; d3 n8 I% T

0 P3 Q  t; a9 y/ h8 I5.查询RTOFF,直到RTOFF位变1,已确认写操作已经完成。
% G, D5 \4 {) O% ?' h2 G; G5 U, G! G6 C  A% A8 f
仅当CNF标志位被清除时,写操作才能进行,这个操作至少需要3个RTCCLK周期。
! |( ~/ u' t0 q7 y
0 I" c+ u+ M; f- CRTC相关库函数. h( W+ }0 X6 r% U5 c, l6 [
RTC时钟源和时钟操作函数:3 ]2 ]- U6 J7 D( o5 a1 I! j
  1. void RCC_RTCCLKConfig(uint32_t  CLKSource);//时钟源选择
    3 p% {8 T( H/ a8 l- `  O9 ?: u
  2. void RCC_RTCCLKCmd(FunctionalState NewState)//时钟使能
复制代码
1 z$ d/ A* U) }$ F; V# J& s
RTC配置函数(预分频,计数值):4 T' p" A) u1 {- @* m
  1. void RTC_SetPrescaler(uint32_t PrescalerValue);//预分频配置:PRLH/PRLL
    . G% D; V5 }( S
  2. void RTC_SetCounter(uint32_t CounterValue);//设置计数器值:CNTH/CNTL+ x* \" ]7 P8 ^. g8 g  s
  3. void RTC_SetAlarm(uint32_t AlarmValue);//闹钟设置:ALRH/ALRL
复制代码
: ?; r* O' X+ R' J/ ^4 n
RTC中断设置函数:. Y$ f+ M; t4 G) z0 `$ @2 v
  1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//CRH
复制代码

% Q0 Z1 g) f7 p) X) i+ C  J, ?" i7 fRTC配置函数:$ ^2 s3 v. ~+ U) k) y1 j( @
  1. void RTC_EnterConfigMode(void);//允许RTC配置 :CRL位 CNF
    # W) ^' T, T) @! p# E) w4 M
  2. void RTC_ExitConfigMode(void);//退出配置模式:CRL位 CNF
复制代码

. S' d; i4 h: |) {& K' hRTC同步函数:
" W3 `1 f. b, }% A9 [% F
  1. void RTC_WaitForLastTask(void);//等待上次操作完成:CRL位RTOFF4 K6 P+ ~' K" S" L7 ^
  2. void RTC_WaitForSynchro(void);//等待时钟同步:CRL位RSF
复制代码
, \' H) u% l/ m# [5 `  _/ m: p
RTC相关状态位获取清除函数:, r5 K9 R' h% V8 K" K
  1. FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);; B& l6 Z! v: a$ l0 B
  2. void RTC_ClearFlag(uint16_t RTC_FLAG);, Y3 W% ^1 b( I5 D  C$ I7 A' I
  3. ITStatus RTC_GetITStatus(uint16_t RTC_IT);6 Q: y3 Q% n; t+ l. |) B$ j
  4. void RTC_ClearITPendingBit(uint16_t RTC_IT);
复制代码
; o2 }/ \6 G' c& k( P5 s
其他相关函数(BKP等)
  `: j7 @/ V; D) q0 w, A
  1. PWR_BackupAccessCmd();//BKP后备区域访问使能
    ! \  v; z& J& [9 t% e
  2. RCC_APB1PeriphClockCmd();//使能PWR和BKP时钟
    1 H0 X+ o( O/ J( F* \& d
  3. RCC_LSEConfig();//开启LSE,RTC选择LSE作为时钟源        $ Y4 F+ F9 T+ M' q! [
  4. PWR_BackupAccessCmd();//BKP后备区域访问使能8 [3 F8 S+ V# E
  5. uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读BKP寄存器
    9 v( H0 ^" H5 l9 }2 L. @- |, q6 P
  6. void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//写BKP
复制代码
/ i3 J3 D( B3 t" n7 q& Z4 C
配置RTC步骤6 j% T% F- I& x: |% x
①使能PWR和BKP时钟:
7 O) J( u9 o, s) ?  y
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
复制代码

1 I& J+ y% h7 _0 e5 R② 使能后备寄存器访问:
" J$ G4 j$ H& J9 f- @1 j
  1. PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
复制代码
1 C+ G* A! g7 e+ t3 e- E, W0 x
③复位备份区域,开启外部低速振荡器。
6 q' S5 v- B  S( ]- j! z
  1. BKP_DeInit();//复位备份区域
复制代码

: B, Y5 |5 G& w8 d. F/ G- z) ~④ 配置RTC时钟源,使能RTC时钟:. Y2 ^5 Y2 R/ _: c7 U" ?4 N& }
  1. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟(RCC_RTCCLKSource_LSI 和 RCC_RTCCLKSource_HSE_Div128)
    " @/ |0 c9 o# `4 O) P' n
  2. RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
复制代码
9 p+ t4 X* ~4 y3 W: d
⑤ 设置RTC预分频系数:RTC_SetPrescaler();
% [% {: i3 e1 h0 Z
  1. RTC_EnterConfigMode();/// 允许配置        - ~% B# I+ P; w4 y7 ~& G) v
  2. RTC_SetPrescaler(32767); //设置RTC预分频的值# H3 M4 h3 L2 P8 C, A6 M8 \6 Q
  3. RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
复制代码

/ x- S, M& E$ N3 d8 }⑥ 设置时间:RTC_SetCounter();1 V, ^: Z9 J; O
  1. RTC_EnterConfigMode();/// 允许配置; v+ J4 `6 F+ B- @
  2. void RTC_SetCounter(uint32_t CounterValue);
    " q5 P) |' r5 m
  3. RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
复制代码
& G+ v5 S3 d0 A: c
⑦开启相关中断(可选):
' m! G+ {/ I: `. o! d  O8 \
  1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
复制代码
. F4 o4 @" @4 Y5 L4 S3 Q
⑧编写中断服务函数:% h) V$ I. p8 n2 ]& O
  1. RTC_IRQHandler();
复制代码
( \$ W  ^  G9 m+ T6 ^. e0 T/ m( J
⑨部分操作要等待写操作完成和同步。
/ p; C) f7 v8 F
  1.    RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成* K( p5 J" S8 Z7 T+ R
  2.    RTC_WaitForSynchro();        //等待RTC寄存器同步
复制代码
( Q5 \. q, e$ _) H' N
具体的代码,库函数写的太多了,我会用CubeMx配置下,用HAL库写一个例程,几十行就可以解决RTC,3 m$ a6 o0 F" N* H, ^- C
/ n$ R0 N4 ?4 i' \9 c  @4 I; o

# e& Q: ]3 R4 U$ P6 A) s% [
  K/ \+ M; G( p
3 e% ~6 \- F! |+ o& E/ E( i7 S
收藏 评论0 发布时间:2022-3-23 15:00

举报

0个回答

所属标签

相似分享

官网相关资源

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