STM32H750 的实时时钟是一个独立的 BCD 定时器/计数器,且带了日历功能,它提供一个日历时钟、两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。 此外RTC 还有自动唤醒单元,RTC还可以补偿闰年闰月等等,还有备份区域(BKP)写保护,这些这里不细说了。
, L& D5 ]7 i9 K! ~ RTC 的简化框图
) h" t7 J/ U+ U7 m4 S" R% s! O; N
6 i, M$ u) E" B' _7 }
6 H' h+ [0 `7 ?: W1 `时钟和分频STM32H750 的 RTC 时钟源(RTCCLK)通过时钟控制器,可以从 LSE、LSI、HSE 时钟三选一,如图所示,有两个预分频器RTC_PRER ck_spre 的时钟可由如下计算公式计算: Fck_spre = Frtcclk/[(PREDIV_S+1)*( PREDIV_A+1)] 图中,ck_apre 也可作为 RTC 亚秒递减计数器(RTC_SSR)的时钟。 Fck_apre的计算公式如下: Fck_apre=Frtcclk/( PREDIV_A+1) 当 RTC_SSR 寄存器递减到 0 的时候,会使用 PREDIV_S 的值重新装载 PREDIV_S,得到亚秒时间的精度是:1/256 秒,可以得到更加精确的时间数据。 . S7 F* f J8 y1 A8 {* v
STM32CubeIDE 配置默认情况下是如图 ; p/ }7 c- X3 a8 D+ O) R- `
, V& }* k5 B% i
4 ?' r4 u+ J, U k% p: s0 r3 a一般情况下使用LSE,这里我们需要在RCC使能
, \: ]" [5 e: g% X1 B' Z/ _ v7 Z
) K+ y/ J" t: P, p& f
! F* q1 ]; Z/ U' a- ?- X然后在RTCC中使能时钟源,如果需要日历闹钟功能的可以在这里也使能上。" I' y. u1 s4 [, F( i5 B* E
! g0 \, |- H. k2 k( p
2 t: {" l8 y0 u% b( Z, p
6 N" c0 [( U8 G& E4 `5 k2 {; l" v0 Z0 h
公式如下: RTC时钟频率 = RTC时钟源 / ((Asynchronous Predivider value + 1) * (Synchronous Predivider value + 1))= 1Hz,也就是1秒 之后到时钟配置里面可以看到已经使能了 ! k6 d o; o+ H# r9 N4 m
* C! G0 g3 R- M0 C8 k+ |/ h0 f
& |* N g$ Y- K+ u' m; E: K初始化 - static void MX_RTC_Init(void)" o- T! @! J2 Y5 M
- {
$ ?& F! Z D+ D, u; `
# o$ _, C( V4 n, `- /* USER CODE BEGIN RTC_Init 0 */
8 J0 H6 I8 ~$ `0 v3 r - 6 f! D4 Z/ g+ {
- /* USER CODE END RTC_Init 0 */
' z, c# K. H2 D v
+ t R% N) L1 H! H( h; N- /* USER CODE BEGIN RTC_Init 1 */
1 y% `! e @' X" L L2 x6 p
6 g% H5 R' P4 Y3 Z' S- /* USER CODE END RTC_Init 1 */6 t6 ~& [6 i+ z$ w+ o+ d( A
- /** Initialize RTC Only
8 |% D% u k ^- F- y0 P8 C - */, w) v% S$ U( z. p4 k4 p8 x
- hrtc.Instance = RTC;) V. }, [9 g/ e$ d
- hrtc.Init.HourFormat = RTC_HOURFORMAT_24;+ t9 B/ e/ F, l4 q; F# K" x( B
- hrtc.Init.AsynchPrediv = 127;
- O) J* b% R2 Z# k; d1 Y5 t - hrtc.Init.SynchPrediv = 255;
# h' f- Y/ _# A: d ~* M+ p - hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
! k2 a, P7 E0 x9 u - hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
! {! [+ A' T- g6 d4 g6 v) E. W" e. Z - hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
/ ?# l! T% W+ K - hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
, W! R2 L1 [' |) E! v l1 { - if (HAL_RTC_Init(&hrtc) != HAL_OK)
1 X7 ^4 |( V5 S) Y. T: [) H - {
5 A; I K2 A, g7 o - Error_Handler();
7 O8 j9 q/ ?" A8 a! l7 k - }; l! V: y0 |0 @; Q" y& D
- /* USER CODE BEGIN RTC_Init 2 */
; S8 ]0 d- v. G% A$ l' l3 K - , L! U0 V; I3 ^6 j) z
- /* USER CODE END RTC_Init 2 */
% ~; P( f* E3 h2 t0 R- H, [
7 b. g+ O0 V) }! }* x' U0 F" ?- }
复制代码
) x* z! @2 `6 @$ w5 B" R3 j7 T v* m
可以看到outline里面有很多我们需要的函数,那么自己扩展就可以使用了
. t& y% N' P0 R- M* v* o
: c$ K; \* U( O7 h5 |9 K, ~/ |+ J& I" a7 Z: n) l8 X+ y
This function configures the hardware resources used in this example - void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)& Y( X: q0 V$ m X, i9 `
- {
D) D4 i2 G& A7 Y# Y - RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
: K( \& t1 K) I/ g; H/ u3 ^ - if(hrtc->Instance==RTC), r4 C& ~5 Z5 @/ T7 e( X" @
- {. C8 ^ n& O$ y+ z; K- G' r4 r/ y
- /* USER CODE BEGIN RTC_MspInit 0 */6 F6 C: M0 |# B; J
1 Y6 B. V4 t/ ~* y2 f% k- /* USER CODE END RTC_MspInit 0 */9 ?) f% d7 D9 a# V& m3 s
- /** Initializes the peripherals clock
2 {, c! U! \" H7 E! t5 N: t1 B' K - */
4 G- v, f4 p) }! _% c8 s/ V! E - PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;5 {0 ^7 {3 b: U" V
- PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
h! F+ ?7 }/ ~) |) J3 ^( s - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK), B) X* Y2 T7 F& g, x1 Z( Z r' ]
- {) V3 G6 m* u6 @" Q- ]
- Error_Handler();
K! N& j/ b1 m0 X# f3 ~ - }5 s- |4 Q& T. \* n2 V" W
" ^+ n7 A% v% v) a5 p0 q) ^# w {- /* Peripheral clock enable */( S8 e. X a+ C0 J6 f$ @# K
- __HAL_RCC_RTC_ENABLE();, F, {5 p8 W$ H# r( G- Z, G; S: u
- /* USER CODE BEGIN RTC_MspInit 1 *// c8 c9 A- J" \( V9 e: |2 b
. i6 @0 b, T2 g2 u$ s8 `- /* USER CODE END RTC_MspInit 1 */2 H* S( N5 b8 L* y
- }
( l6 G$ S3 N: n! U
% r" U: l A2 x( e- }
复制代码 最后,可以按需定制自己的实现方式,RTC是特别实用的一个模块了。2 }$ H7 {! @3 i
8 K/ b- m! j c, K3 h, G7 X$ X) H3 p r# q/ ^
5 G0 }8 s: q& L作者:李肖遥
) D: v z+ J& t; J: N! ] |