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

STM32LL库教程之RTC连续闹钟

[复制链接]
海迹天涯 发布时间:2019-1-9 18:11
     在项目中使用STM32RTC闹钟过程中遇到几个问题,百思不得其解,在百度搜索中也没有找到相关内容于是决定打开数据手册深入学习下这个RTC。以往虽然也有使用过RTC这个外设,不过都是拿来主义,导致这次遇到点问题就懵逼了
# E8 U1 ^0 I0 Y
# m% y# G5 U7 @: |1 R   先用神器配置CUBE一下:
! x6 I1 V/ u# k# `5 r4 B 1.png
( }4 R) ~% ~0 D9 J 2.png 3 L3 j) }& T5 l! Z
3.png
- T* x* b; B2 D$ n 4.png - H$ j% s3 c& R- c9 {
然后点一下齿轮生成代码。7 y; X7 I$ r: y& p
RTC初始化代码,做了一点小改动:' s+ M6 Z4 `- ?% Q. m0 a
void MX_RTC_Init(void)
& q; P5 R* P3 C4 o5 y; t{2 m/ k! g* Z# E: ?+ U
  LL_RTC_InitTypeDef RTC_InitStruct;& [- p# K" G* b3 L6 J. I3 ]. e" ~
  LL_RTC_TimeTypeDef RTC_TimeStruct;
' n- f) v6 L" x. C  LL_RTC_DateTypeDef RTC_DateStruct;1 L7 O( a% a" o
        4 X% _4 E* N: C: u! D
        LL_RTC_AlarmTypeDef RTC_AlarmStruct;
- @8 V5 |  ~0 }0 h  /* Peripheral clock enable */8 K8 m+ i; T4 y' E# L4 z  P- g8 A
//  LL_RCC_EnableRTC();0 _5 o* O  |% g3 C6 @+ Y
        6 t4 T! H$ g2 }7 L2 K7 b$ z/ u+ h
//        if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2)7 c; f* I: V. [7 j( o7 e
//        {
7 {/ A( G. _! H+ T- n. l- y/ K+ `: b5 r3 a+ M5 A
                        /**Initialize RTC and set the Time and Date * m: q, M# V2 J# p
                        */; ^( ^* d9 B$ C6 a* r5 N9 F* P& p
                RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;  M0 k! z' f2 L7 I+ }% O& d) L
                RTC_InitStruct.AsynchPrescaler = 127;
& D6 B9 v3 e, v9 V9 V                RTC_InitStruct.SynchPrescaler = 255;* v4 F, o: c: l# ^* B7 z
                LL_RTC_Init(RTC, &RTC_InitStruct);
0 x( [- P+ k% g1 h) q- T0 j% s
6 O0 t1 h, K6 K) E                        /**Initialize RTC and set the Time and Date
; r9 U# m3 `! x" J% |3 O* T! D/ O                        */6 t% s4 G, s1 b) ?' B+ W% h) S( B
               
( B& p- b+ k( n# X! _% D                RTC_TimeStruct.Hours = 12;! P1 X  h3 a5 r+ b+ `
                RTC_TimeStruct.Minutes = 50;
( s; V6 b; ]9 x+ O                RTC_TimeStruct.Seconds = 40;& z- G1 \# A% @7 d( H' k# `
                LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_TimeStruct);6 k( Q0 b. b$ _5 D( X# R) J
8 U, a# P7 [: k
                RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_MONDAY;+ X) V2 G( b2 n1 }
                RTC_DateStruct.Month = LL_RTC_MONTH_JANUARY;
9 i# X( U( e- F; h# {6 }/ [1 X                RTC_DateStruct.Year = 19;! ~. I8 \' P* B
                LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_DateStruct);
2 u4 D5 s9 R7 E/ I$ Q: a9 e! i- V5 P0 k& h, J( P
                 LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);) h8 k+ f# D, U: ~; G# {& M2 }
                 , J9 z: Z+ X% o$ v: s0 K: _/ Z/ c
                if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2)
! |) l" x0 f9 w" G( \$ ]) @4 ~                {. f$ g0 g7 E+ F( @6 v3 i
                        LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);: ~5 c3 d- ~! b( @  M& m
                }7 t+ r( V6 U' F- j: D$ j
    /**Initialize RTC and set the Time and Date 0 k  x9 ?2 x, D' g; x. d  _
    */: U* f7 H, L* {* w

# }7 u  X- L$ p                if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2): G# H$ l8 a* i2 `. C" u6 l& h
                {; ^% M8 I1 O% @* q( s+ H9 K
                        LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);
- t, ^( s. [% f) L5 s2 n                }
- @2 ?; J7 v0 G- a: Q//  }8 {8 b/ U5 i) o4 X( M
       
& [; A, @/ E$ j3 h  V1 G        /* RTC interrupt Init */
, l9 \$ z! n! ~% C8 v) z3 ]        NVIC_SetPriority(RTC_IRQn, 0);0 Z# p8 k& u% E) I
        NVIC_EnableIRQ(RTC_IRQn);7 U: d! ^9 t( m* J- o0 _  ~
        /* RTC Alarm Interrupt Configuration: EXTI configuration */
1 Z" R5 f, @% G5 J$ u3 P  LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_17);
1 M" z; v2 I. u: }  LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_17);
2 n" d# r2 |) p8 q               
. @+ L% s# x, G//        RTC_AlarmStruct.AlarmTime.Hours =  12;! m$ d2 d2 g! J6 m& b8 ]: i
        RTC_AlarmStruct.AlarmTime.Minutes =  51;# k/ z& W( A: z2 F3 a# _, U
//        RTC_AlarmStruct.AlarmTime.Seconds =  0;
+ [4 o# ~% w+ l+ g; m6 M; ?4 z  V+ \//        RTC_AlarmStruct.AlarmTime.TimeFormat =  LL_RTC_HOURFORMAT_24HOUR;. V( n; |: g* d/ h. M- ?8 r; v. b
//        RTC_AlarmStruct.AlarmDateWeekDay = 1;
9 B* z. ~0 Z2 n+ b//        RTC_AlarmStruct.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;) R& S$ A4 p. |& O
        RTC_AlarmStruct.AlarmMask = LL_RTC_ALMA_MASK_DATEWEEKDAY|LL_RTC_ALMA_MASK_HOURS|LL_RTC_ALMA_MASK_SECONDS;//LL_RTC_ALMA_MASK_NONE|LL_RTC_ALMA_MASK_MINUTES;1 Y- `3 n/ w# E8 }# s3 o  M
        LL_RTC_ALMA_Init(RTC,LL_RTC_FORMAT_BIN,&RTC_AlarmStruct);
& b$ x% B1 ~* H2 ^; ]* ?  LL_RTC_DisableWriteProtection(RTC);       
9 A1 v2 \% f! y/ a9 j9 a# p; ~) X; F        LL_RTC_ALMA_Enable(RTC);5 A! ]# e1 G) H2 G' ]
        LL_RTC_ClearFlag_ALRA(RTC);
/ ~' e. K; c+ ?8 O        LL_RTC_EnableIT_ALRA(RTC);) t1 l+ {5 W6 _) [
        LL_RTC_EnableWriteProtection(RTC);
, N4 A. k/ M4 E1 q, V6 w8 O}8 d; V7 n+ ?1 j  T) u
RTC的闹钟中断是内部连接到外部中断控制器的,所以使能了还要记得使能外部中断线路和设置中断方式,手册上写的闹钟中断使用17号且只能配置成上升沿
4 g0 E! G5 [) g/ b! M 5.png 6.png
% J& r9 t7 L& ~, f
* N* K4 e. z  T$ N2 i* x5 m时间走到设置的闹钟时间后就会进入中断了
9 i# }. O4 I3 I+ G  V+ w4 h! k9 G5 y6 tvoid RTC_IRQHandler(void)
  w8 I( B% c2 ]; `/ x{
7 ^# ]3 }. t: G( p; V) `        if(LL_RTC_IsEnabledIT_ALRA(RTC))! |3 B+ {, C) z  j9 w
        {
+ U; g! K; v! Q                if(LL_RTC_IsActiveFlag_ALRA(RTC))
* r0 u/ W6 g; F( |: N2 m                {2 j: x0 b( `0 {6 |4 _9 L, j
                          LL_RTC_DisableWriteProtection(RTC);       
* \$ r6 C0 @5 X1 O3 n* \                                LL_RTC_ALMA_Disable(RTC);& r; A( ~/ J8 M/ R( b) A+ L
                                LL_RTC_ClearFlag_ALRA(RTC);4 M2 [! b9 {7 K3 N, U2 H
                                LL_RTC_EnableWriteProtection(RTC);       
1 Y  V% D9 O! C; _$ ^" `3 m                          LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_17);. G6 F8 Y- K- N+ ?! n6 Q
                          rtc_flag = 1;, `* s2 {! b2 N6 O# Q
                }
! O9 F5 d1 c: X. b, Q# m& g! X        }( ]- O6 z; F2 h+ F- R7 B! N

' E; W: G( N6 U' |* p8 l9 V2 S# Z5 O}6 `" }2 U- e! d( |

  Y8 j! ^1 d6 x; W$ Y% l这里需要注意使用库函数操作RTC后一般都会使能写保护寄存器,所以到中断后先取消写保护然后关闭闹钟A并清除闹钟A的中断标志和17号外部中断标志,这里我用了一个 rtc_flag代表进入了闹钟中断,在主程序中检测到这个标志后设置新的闹钟时间(这里关闭闹钟是为了后面重新设置闹钟,因为不关闭闹钟是无法重新设置闹钟的,我之前出错就是没有看数据手册导致闹钟只能第一次进中断)。. o* |) T0 m6 {
8 `8 V3 P% H% m6 i7 L* N7 l
在主程序中重新设置新的闹钟:
* @7 Y7 d# R' ~) C& F
0 Q! s5 D3 J0 c+ V5 x5 Xvoid RTC_AlarmA_Callback()
! R6 F: k+ V7 i- s+ h{
3 |2 P* d! z+ d: d/ z8 c1 h        LL_RTC_AlarmTypeDef RTC_AlarmStruct;
) A1 k: e9 w8 _* ?9 J# p5 J% v1 A
0 u; v  W0 m- H% G//        RTC_AlarmStruct.AlarmTime.Hours =  12;# i1 q2 c1 `! w$ [3 X
        RTC_AlarmStruct.AlarmTime.Minutes =  52;
# x5 V6 v- q" i//        RTC_AlarmStruct.AlarmTime.Seconds =  0;$ B- t2 o6 {/ a6 Y  i% j3 m
//        RTC_AlarmStruct.AlarmTime.TimeFormat =  LL_RTC_HOURFORMAT_24HOUR;; R- K( {: e  ~/ X
//        RTC_AlarmStruct.AlarmDateWeekDay = 1;6 a7 [) d$ J8 D
//        RTC_AlarmStruct.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;  {) D% g; f9 p" f
        RTC_AlarmStruct.AlarmMask = LL_RTC_ALMA_MASK_DATEWEEKDAY|LL_RTC_ALMA_MASK_HOURS|LL_RTC_ALMA_MASK_SECONDS;//LL_RTC_ALMA_MASK_NONE|LL_RTC_ALMA_MASK_MINUTES;
! M% V7 i4 {$ w  [1 n9 b! X8 o4 i        LL_RTC_ALMA_Init(RTC,LL_RTC_FORMAT_BIN,&RTC_AlarmStruct);+ W7 q. l1 O, V6 d$ `
        LL_RTC_DisableWriteProtection(RTC);       
; ~  q9 [& d+ @6 n) C1 }; j        LL_RTC_ALMA_Enable(RTC);+ h$ Y( L0 `: H8 O* B3 n0 F
        LL_RTC_ClearFlag_ALRA(RTC);  f' y* ?$ d* Y0 R
        LL_RTC_EnableWriteProtection(RTC);
" }2 a" l5 @& o+ ^}
  y3 A* L2 g0 L7 E6 E6 g: n0 d# ]/ R& z" Z5 l6 ^) }
这里设置了闹钟时间后记得重新使能闹钟A,最后再使能一下写保护,防止意外操作改变RTC里面的数据。只要每次进入中断后读出当前时间并设置新的闹钟时间,就能连续的通过闹钟中断做需要准时做的事情了。1 k: ^* s7 T, \  r  V1 G

) {8 T# _1 S- x2 Z. p; M  总结一下,RTC设置时间日期寄存器的时候不是直接设置,而是需要先进入到初始化模式才能设置,设置完成后退出初始化模式开始重新按照设置的时间计时,设置闹钟中断的时候要记得先取消写保护,并且要在闹钟关闭的情况下写入闹钟时间,写入完成后开启闹钟。设置对应的闹钟外部中断线就OK啦。就这样吧,有没写到的下次补充。
0 U/ Q; s2 B9 z8 b4 n* c3 C
- ^1 T' p5 Z3 N- _- V9 l5 _4 G, F  n: Z, N  O2 _! z: X. C# A7 e

STM32L071_LL_RTC.rar

下载

10.75 MB, 下载次数: 336

赞 收藏 评论10 发布时间:2019-1-9 18:11

举报

10个回答
STMCU-管管 回答时间:2019-1-22 13:31:34
谢谢分享
sa090843 回答时间:2019-1-22 16:54:25
感謝分享
五哥1 回答时间:2019-1-23 01:49:55
谢谢,这个又学了些东西
烤猪 回答时间:2019-6-30 13:29:53
感谢
engerHi 回答时间:2019-7-3 16:26:55
谢谢楼主分享!
frank171 回答时间:2019-7-4 09:15:11
很仔细了,谢谢分享
zhouxb 回答时间:2019-7-4 14:58:54
好厉害的样子
" A! t2 C/ Q- _5 `; U4 c/ [6 a1 o
sym_cool 回答时间:2019-12-6 20:45:20
大神,我参考了您的代码成功实现了stm32l051的RTC闹钟唤醒待机模式,请问您代码中把LL_RCC_EnableRTC();注释了,这个作用是什么呢
zhenshanmcu 回答时间:2020-3-18 13:30:56
我也看看研究下。
过去痕迹 回答时间:2022-7-29 15:29:30
t同样遇到了问题 不过我是G0系列  ^2 r+ C, S$ n8 V- A6 t/ v
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版