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

【经验分享】基于STM32使用HAL库驱动RTC时钟及闹钟功能

[复制链接]
STMCU小助手 发布时间:2022-4-10 17:01
(一)工程配置
+ T# I3 i  J( D0 S我使用STM32F103RB这一款MCU,首先使用STM32CUBEMX创建工程,配置主时钟和RTC时钟,我板子上是使用的外部的32.768K晶振供RTC:
9 n1 x* W  e5 P6 [8 ~7 f; b0 t; s+ A( T; s9 N
C3{M])]J4ZHAZ}[7HY3$V61.png 8 h% _- `) k( l4 D
97GQ`99{Q(TOSDHE5R}`J8G.png
5 ^6 s( M8 u' k3 O$ h& `, D% [, E1 w; @7 e1 x
配置了两个LED灯:

% L! S: u0 n+ v
& ~+ f1 M* b+ P+ ` E1TKCWX3P$W{AZ0{TE)NX]P.png
% a( L' |. m3 U' G& ^
" J2 n( {3 }& M配置调试下载接口为SWD(此步骤如果不配置,你使用stlink的话下载一次程序之后就再次下载就会找不到MCU):
' P* i- |7 M$ v3 W' ?; ^2 q% m- p: O* E. P- e
`6T2@4B$L10P(QAQTU4~Q1M.png
6 p4 s  X" A) l, c, V8 Z0 e( c+ m" [- g8 F( E% P: F$ d4 r
配置串口1:
" |3 r" p" A* q4 U8 X+ h2 g* f. G0 r* }' k5 G- h: X" h3 q; p
O~75A%RI1CY(35W%_8_27QQ.png
) v' Z$ U( w1 m( p
; i- e) B7 R% S0 m+ ^配置RTC时钟,激活日历和时钟源,这里我设置时间为2020年12月25日0点0分0秒,设置闹钟提醒的时间为3s:
* h0 S0 @! T: C; t, b. B  b( L5 l; l7 J: j- ^
01O~~)LP[7AT~BC{8ZMQRCM.png 5 Y  F$ f3 W7 M' y
: c0 z1 b( F- [/ n2 ]
使能RTC闹钟提醒功能的中断:& v* U5 {" V: \4 k* j: @2 Q* _

1 x- d, P* h7 y( h1 _  D( Y
0@S}$_5{DKF`~OL1(71XUYY.png
# B; m, i1 Q! V, d' |
0 T  R, R9 @7 D' L2 z+ L8 e; z其他工程设置:
/ o  e- k: ^( p

) [0 y! q5 A7 H9 s $KVEO9DZGAMPO8E3%RRVGGU.png ; J* v( a# F5 c2 e9 ]8 i$ X+ ?+ x# i3 f

. _$ D+ }/ E4 o8 s然后生成工程就可以了。
4 C) k2 m( J5 z8 t
; e! ?# J; [' G2 J" k) p. C0 Q8 Q8 s(二)代码编写

+ X4 u6 q+ a+ J$ c重定向printf函数:1 W3 t7 w( ^8 y8 F5 p9 e# W
6 q: C. o8 v1 `( K
  1. int fputc(int ch, FILE* fp)6 ]0 S6 q: b, `7 c
  2. {: y: Z0 w# @, W4 A4 u
  3.     while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) != SET);0 m$ k0 i) M3 p" N0 S6 b( o
  4.     huart1.Instance->DR = ch & 0XFF;
    $ W6 r" A: r7 F
  5.     return ch;" e% @7 w$ O; v* T1 I, C  J  R9 R
  6. }
复制代码

3 V( f1 V/ ~9 o8 O3 h6 FHAL库获取RTC时间的函数有两个:
5 u; |; N/ F! f2 \# ]% BHAL_RTC_GetTime:获取时间, j. f1 D( ~+ J+ {/ |6 `
HAL_RTC_GetDate:获取日期2 O4 }$ h( O) ^* l9 C
" s) W( T( C, P- `
这两个函数的第三个参数是格式:RTC_FORMAT_BIN和RTC_FORMAT_BCD,BIN格式就是十六进制数值直接表示的时间数值,BCD格式就是用数值的十六进制面值表示时间数值,例如表示第24分钟的时候,BCD格式的分钟值就是0X24。
' T- ^  ]* ~/ m
- |( W& K- E: C, K2 I) `注意:
这两个函数调用是有先后顺序的,必须先调用HAL_RTC_GetTime然后在调用HAL_RTC_GetDate。- a. F) c4 y! F9 l' Y5 J) R3 H

2 y* y2 v. W) v可以通过以下两个函数设置时间:5 G) H- }( H3 m. H3 E+ p  \0 I
HAL_RTC_SetTime0 w, m- y/ e/ \
HAL_RTC_SetDate
$ O- ^3 I: T0 Y* c. H' q9 `) x, j- b9 Z: d6 U/ ]
这里我简单的把时间设置的函数做了个封装:
" A3 a+ P3 C: l( w0 W" C8 r+ x7 m1 k, a. U* C' |/ u
  1. #pragma pack(1)/ E' D- ^+ V) r: _0 n+ o
  2. typedef struct0 l' u( N# x8 S9 k! p3 }6 X
  3. {
    8 D% k2 X* N. h0 j; |$ g+ p" T9 J. f
  4.     uint8_t Hours;4 |( o0 U2 L1 c: L# _
  5.     uint8_t Minutes;6 v: @/ z9 e& J4 _2 i8 |
  6.     uint8_t Seconds;
    0 {% V' J' J& P! C! Y# W" n
  7.     uint8_t WeekDay;* N  n# F' y( {$ i& y# v
  8.     uint8_t Month;
    1 H& i6 S! o% j# ^
  9.     uint8_t Day;5 j4 o1 U% ?6 X, [' V4 L
  10.     uint8_t Year;
      B8 o$ t. ^4 z# {" W$ @  @
  11. } rtc_time_t;
    " Y+ `0 x, @; w' I7 }
  12. #pragma pack()
    5 l, y' B7 K; G% M# z& K
  13. # D7 l3 f* V9 ~- O! U) z+ a5 g, m
  14. * q' K6 H  Q: z! o2 u
  15. void RTC_GetTime(rtc_time_t* time)& R6 x: |* e2 Y' @/ {$ ]( d/ _" N3 V( N
  16. {
    ) p- F0 z- G' Q+ b; W
  17.     HAL_RTC_GetTime(&hrtc, (RTC_TimeTypeDef *)&time->Hours,   RTC_FORMAT_BIN);% |7 m3 m' ?7 j* Y; t, {- A
  18.     HAL_RTC_GetDate(&hrtc, (RTC_DateTypeDef *)&time->WeekDay, RTC_FORMAT_BIN);# V( Z! T9 D  Q+ m! F: d
  19. }
    - |6 |& u( B3 h. O3 r' K7 c0 c

  20. ' k% y5 U, i/ d/ H+ W% L! ]4 S' _- o
  21. void RTC_SetTime(rtc_time_t* time)
    ; w" r2 u6 E) t
  22. {
    0 e# B. G6 I' ^6 y* A) K# b
  23.     HAL_RTC_SetTime(&hrtc, (RTC_TimeTypeDef *)&time->Hours,   RTC_FORMAT_BIN);. J. z% m4 d* j4 F8 M
  24.     HAL_RTC_SetDate(&hrtc, (RTC_DateTypeDef *)&time->WeekDay, RTC_FORMAT_BIN);5 F. E& M! m: _
  25. }
复制代码

: D, {- A* Q( r6 a覆写闹钟时间回调函数:4 |' w/ E9 V  O
" E6 g3 |3 e0 M. i  k
闹钟事件的中断设置,要看MCU支持的是秒中断还是时间中断,比如10X系列,要通过当前时间去设置下一次闹钟,而40X系列的可以直接设置时间。
0 R& e/ S6 h# J/ @& \
; e/ K5 e6 _3 y
  1. void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)) e. A- P2 G6 r
  2. {
    & x: L" b% b3 d) P6 U
  3.     RTC_AlarmTypeDef sAlarm = {0};: U; v/ b( a- @3 s2 B/ e3 B; g0 Z
  4.     rtc_time_t tim = {0};
    , a4 ]9 v; O& ?$ Y+ q$ N; ^
  5. - g% y  Z& N# X) U2 t) P
  6.         // 获取当前时间
    $ ?" |6 J* k6 Y# _8 t1 P5 W
  7.     RTC_GetTime(&tim);
    . c$ v4 A7 m7 `3 P3 f

  8. 7 _# i+ J- U1 O' V" z* u+ X; K
  9.     sAlarm.AlarmTime.Hours = tim.Hours;7 I& m! |4 ^( e6 u3 ~- S6 ]! U: j" ]
  10.     sAlarm.AlarmTime.Minutes = tim.Minutes;) o" `/ f* t6 M& T3 B+ B- m
  11.     sAlarm.AlarmTime.Seconds = tim.Seconds + 3;  /* 设置下次闹钟提醒时间是当前时间的3s之后 */2 o4 r/ b9 q- X  ^5 Q9 s5 g
  12.     sAlarm.Alarm = RTC_ALARM_A;
    + g' Z# Y( g$ U7 c7 ~, P' O
  13.         . y  ^0 J7 s8 O  O0 a4 z
  14.         // 再次启动闹钟中断事件. \5 E6 d) f' y/ n3 z% G6 B
  15.     if (HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
    6 Q. W- d' K2 c: Q) y1 N
  16.     {
    / S' I1 ?1 B3 r6 ~# H/ l' D
  17.         Error_Handler();6 f3 o+ C$ H  z$ O
  18.     }
    0 p. F2 |, M; w
  19.         
    ' h0 `1 m/ B0 n+ r3 C% Y5 L
  20.     printf("HAL_RTC_AlarmAEventCallback\r\n");
    & C$ p& d. c, v3 K5 ]) B
  21. }
复制代码

$ q* o/ C  h8 T' B+ K6 L, D* g9 Smain函数:+ ]% v, B: X# {) P5 R1 ~( o7 d; L

6 w# E  x6 `5 v$ S  ]& J7 G
  1. int main(void); S) }. q2 s) W! V+ i5 O
  2. {4 W( g' Y' j' [" m& n
  3.     rtc_time_t tim = {0};
    9 x/ G5 B, Y: ~: {
  4.         6 m2 U3 B0 j/ e0 n/ e2 s9 q
  5.     HAL_Init();6 s7 f  ^- Z; P, R
  6.     SystemClock_Config();$ g" Q; g( \( b& W! T1 r8 K
  7.     MX_GPIO_Init();6 q" w" u& s" e7 V
  8.     MX_USART1_UART_Init();+ w( w) L) l# j& C$ j1 Q4 u
  9.     MX_RTC_Init();* S6 b& P6 v/ b. ]0 ?3 I- X+ ]
  10. ' K" I5 t2 H( ~/ ^0 ]7 C& z
  11.     while (1)  P% g1 v! J# j( ^- P
  12.     {/ s7 i9 t- }) G4 ?' M  |2 Y4 J) j
  13.         HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);8 W* e# ~" s, x
  14.         RTC_GetTime(&tim);
    : t+ m5 G5 B. @' ?5 I4 |! m
  15.         printf("%02d/%02d/%02d %02d:%02d:%02d %d\r\n", tim.Year, tim.Month, tim.Day, tim.Hours, tim.Minutes, tim.Seconds, tim.WeekDay);4 D1 S1 [& S4 p6 G! N1 ]
  16.                 HAL_Delay(1000);
    3 M; r, `, c) m+ n" J
  17.     }
    0 ]7 E( b5 z7 |6 F2 }/ ^* {
  18. }
复制代码
* A/ O1 ~: t6 a2 ~
(三)运行效果, T; t9 [) \: k' o7 A% F6 V

+ R! A1 W' Y1 j& _/ w* l/ T 20201225092230509.png ! r  W' @1 f4 N& k/ e
) B" |& T# s. @' g' k5 T: g

) R9 K' t: @( [. X$ [/ Y5 x3 ]. U( @1 L7 Z+ d
赞 收藏 评论0 发布时间:2022-4-10 17:01

举报

0个回答

所属标签

相似技术帖

官网相关资源

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