|
玩转STM32CubeMX | RTC实时时钟
6 \, W3 {0 d+ P" _9 S; y
6 `2 L4 C9 o1 N+ ~% @1.RTC实时时钟简介
. F K( d& G" V+ p5 r: |& t
. D) l, {$ p, W jTM32的实时时钟RTC是一个独立的定时器,RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能,修改计数器的值可以重新设置系统当前的时间和日期
9 p% P4 |' S" I$ g2 YRTC模块和时钟配置系统(RCC_BDCR寄存器)是在后背区域,即在系统复位或从待机模式唤醒后RTC的设置和事件维持不变。但是在系统复位后,会自动禁止访问后备寄存器和RTC,以防止对后备区域(BKP)的意外操作。所以在要设置时间之前,要先取消备份区域写保护。RTC的简化框图如下所示:
$ U- E& t5 y4 c1 o5 T. q6 cRTC由两个主要部分组成:第一部分(APB1接口)用来和APB1总线相连,此单元还包含一组16位寄存器,可通过APB1总线对其进行读写操作;另一部分(RTC核心)由一组可编程计数器组成,分为两个主要模块,第一个模块是RTC的预分频模块,可编程产生1秒的RTC时间基准TR_CLK。第二个模块是一个32位的可编程计数器(RTC_CNT),可被初始化为当前的系统时间,一个32位的时钟计数器按秒钟计算可以记录4294967296秒,约136年左右,一般应用已经足够5 a# e. r% @, T( S1 E2 ~
1 a) e4 t: g9 K- j" r0 L9 C' Q' c! y& [
' o+ t, X5 n6 z2 S! l# l% ORTC还有一个闹钟寄存器RTC_ALR,用于产生闹钟。系统时间按TR_CLK周期累加并与存储在RTC_ALR寄存器中的可编程时间相比较,如果RTC_CNT = RTC_ALR将产出一个闹钟中断,从而实现闹钟功能6 x( ^ m. P2 G8 b5 }
5 p& M; O' {' Q# \9 U9 n7 m
2.硬件设计" \ c+ N+ U8 a% G# d# |; W
) [/ E ]) I& Z本实验通过RTC的秒中断来持续输出时间通过串口1打印出来,并通过设置闹钟中断实现一个闹钟提醒,D1指示灯提示系统正常运行: J( C1 c/ X1 e6 n! j: c
G2 V1 B% J: Z+ K( q$ f; _* t4 t+ S7 e) ^9 j# y+ E3 i# N( C
-指示灯D16 y* [. T: A- }+ A. ^
-USART1串口4 D, ] p. B) s; C8 f$ q
-RTC4 |5 }) W* P8 I- ]+ z
3.软件设计9 `6 \) u G6 M- Y, x
3.1 STM32CubeMX设置0 u" _! Z. @* z2 H; c! ^
; v7 V% b: k7 g" Z. C. {5 l( ]! o
R. c, \: {, B2 O: I➡️ RCC设置中开启外部高速晶振(HSE)以及外部低速晶振(LSE),时钟树中将RTC的频率设置为32.768KHz
& _$ M; H. _* i+ \. p2 j$ g➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平& Q* c3 L% R2 d
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
7 J8 r6 C2 H1 ^9 ~1 Q( k➡️ 激活时钟源,激活日历,选择No RTC Output,设置初始日期和时间
) a& u+ M' Y8 v, Z, q➡️ 使能RTC全局中断和闹钟中断
. B* i" ?8 K$ V9 d; T- O; ^: H" p➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
e6 B) ]+ o% j1 i
4 n6 Q& }3 W+ {! M3.2 MDK-ARM软件编程4 S( T6 ~; s6 e( W8 P, L; N* [: s
4 B) q9 F/ h( x' x7 t$ U
) q& t; B# ?" R( |" J1 W! z➡️ 在rtc.c文件中编写秒中断处理回调函数和闹钟中断处理函数
* a/ A; R9 b0 n7 \- z' z- extern RTC_DateTypeDef GetDate;
$ e9 i; R6 `0 s) b* l- B5 f - extern RTC_TimeTypeDef GetTime;+ k4 X) t2 o: v6 C
- 6 U g' @4 s, a
- void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc){
, \$ d+ A9 h( d - HAL_RTC_GetTime(hrtc,&GetTime,RTC_FORMAT_BIN);
0 s: C4 c5 G- f: d/ Q, t - HAL_RTC_GetDate(hrtc,&GetDate,RTC_FORMAT_BIN);
! M* H! ~ ~$ x# c6 H - printf("Date:%02d-%02d-%02d\r\n",2000+GetDate.Year,GetDate.Month,GetDate.Date);. r8 [; \- T8 L/ p& o, T: a( \
- printf("Time:%02d:%02d:%02d\r\n",GetTime.Hours,GetTime.Minutes,GetTime.Seconds);; @# g. V3 {4 D: c) Y8 e; P
- printf("\r\n");
3 [. f8 @5 \ W3 b - }, j7 ^! c' I/ B( ?" J" |6 b
- 4 @" I: n- k3 P" k9 b9 J f6 J- ^
- void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){
: ?: \$ z! @/ ]& J8 t3 u- g5 o$ C - printf("Alarm Active...!!!\n");" I2 H7 ?+ P8 J1 m n7 {7 R2 S
- }
复制代码 ➡️ 在main.c文件中编写闹钟设置相关代码并开启相关中断, y: D0 i* O$ G* h
- /* USER CODE BEGIN PV */
5 B6 V0 I; T( c. t( a - RTC_DateTypeDef GetDate;
& O6 T- W; M. G' T - RTC_TimeTypeDef GetTime;8 n$ g& z' k' @6 d4 z( q
- RTC_AlarmTypeDef sAlarm;
; H4 n) I- x1 ~/ k' P - /* USER CODE END PV */
- F2 ]; _1 P6 w# D - int main(void){
3 t# B7 b# {) `' Q u$ u - HAL_Init();. G) a f0 v( F6 B5 T" V6 Y
- SystemClock_Config();# ]- i8 @( [7 |9 j
- /* Initialize all configured peripherals */
1 k- V) o' u- B" @' N# ] - MX_GPIO_Init();
# ~, i6 x1 v" P8 c& L { - MX_RTC_Init();, |5 A6 r' S& |# X7 }
- MX_USART1_UART_Init();
" ^4 J" A5 ?$ _! d - /* USER CODE BEGIN 2 */
$ ^/ Q/ J* `0 O( K) U( H - //开启秒中断0 u2 {; H) M' I$ z9 c$ |. e5 T9 o
- __HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);
2 ]9 Q) j; g1 }; X. x( u* M* K - sAlarm.Alarm = RTC_ALARM_A;" I1 W5 r: t! G
- sAlarm.AlarmTime.Hours = 16;" }5 X5 N" m6 w1 f
- sAlarm.AlarmTime.Minutes = 20;4 E- i" f8 r @4 r: Y
- sAlarm.AlarmTime.Seconds = 30;
- Y$ ]7 o7 S6 N; t - //设置闹钟并使能闹钟中断
4 t& `1 O" h" c% E+ l( o$ u, @ - HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,RTC_FORMAT_BIN); 0 `, o5 N8 W" w3 }, C
- /* USER CODE END 2 */0 i; T- K$ G4 W5 J
- while (1){( N) G7 K) ` l3 S9 W- X: E& |% u+ w
- HAL_Delay(1000);
7 `! R) i' K+ O1 F! P# P. D5 m - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);3 l2 v2 `- S1 v- ]( ]; @1 u
- }
4 N+ s3 N# r! J2 a - }
复制代码 4.下载验证3 F9 H1 l% J$ Z/ } i- T3 k) |
" B, I. r, M# X# A
) Y& ~ U$ \) B! B编译无误后下载到开发板,可以看到D1指示灯每1s闪烁一次,串口助手每1s会打印出相应的日期和时间,闹钟设置的时间到后会打印出闹钟中断函数里的相关语句8 o5 s+ m4 B0 U: L( M5 v$ E r( _
3 n. r1 l8 @0 u% |
|