【STM32】RTC程序示例
00. 目錄
文章目錄
- 00. 目錄
- 01. RTC時鐘簡介
- 02. 硬件設計
- 03. RTC日歷配置步驟
- 04. 設置和獲取日期示例
- 05. 設置鬧鐘中斷示例
- 06. 設置喚醒中斷示例
- 07. 附錄
- 08. 聲明
01. RTC時鐘簡介
STM32F4 的實時時鐘(RTC)相對于 STM32F1 來說,改進了不少,帶了日歷功能了,STM32F4 的 RTC,是一個獨立的 BCD 定時器/計數器。RTC 提供一個日歷時鐘(包含年月日時分秒信息)、兩個可編程鬧鐘(ALARM A 和 ALARM B)中斷,以及一個具有中斷功能的周
期性可編程喚醒標志。RTC 還包含用于管理低功耗模 式的自動喚醒單元。
兩個 32 位寄存器(TR 和 DR)包含二進碼十進數格式 (BCD) 的秒、分鐘、小時(12 或24 小時制)、星期、日期、月份和年份。此外,還可提供二進制格式的亞秒值。
STM32F4 的 RTC 可以自動將月份的天數補償為 28、29(閏年)、30 和 31 天。并且還可以進行夏令時 補償。
RTC 模塊和時鐘配置是在后備區域,即在系統復位或從待機模式喚醒后 RTC 的設置和時間維持不變,只要后備區域供電正常,那么 RTC 將可以一直運行。但是在系統復位后,會自動禁止訪問后備寄存器和 RTC,以防止對后備區域(BKP)的意外寫操作。所以在要設置時間之前,先要取消備份區域(BKP)寫保護。
02. 硬件設計
用到的硬件資源有:
1) 指示燈 DS0
2) 串口
3) TFTLCD 模塊
4) RTC
03. RTC日歷配置步驟
①使能PWR時鐘:RCC_APB1PeriphClockCmd();
② 使能后備寄存器訪問: PWR_BackupAccessCmd()
③ 配置RTC時鐘源,使能RTC時鐘:
RCC_RTCCLKConfig();
RCC_RTCCLKCmd();
如果使用LSE,要打開LSE:RCC_LSEConfig(RCC_LSE_ON);
④ 初始化RTC(同步/異步分頻系數和時鐘格式):RTC_Init ();
⑤ 設置時間:RTC_SetTime ();
⑥設置日期:RTC_SetDate();
04. 設置和獲取日期示例
rtc.h
#ifndef __RTC_H__ #define __RTC_H__#include "sys.h"//RTC初始化 u8 MY_RTC_Init(void);//RTC時間設置 ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm);//RTC日期設置 ErrorStatus RTC_Set_Date(u8 year, u8 mon, u8 day, u8 week);#endif /*__RTC_H__*/rtc.c
#include "rtc.h" #include "delay.h"//RTC時間設置 ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm) {RTC_TimeTypeDef RTC_TimeStruct;RTC_TimeStruct.RTC_H12 = ampm;RTC_TimeStruct.RTC_Hours = hour;RTC_TimeStruct.RTC_Minutes = min;RTC_TimeStruct.RTC_Seconds = sec;return RTC_SetTime(RTC_Format_BIN,&RTC_TimeStruct); }//RTC日期設置 ErrorStatus RTC_Set_Date(u8 year, u8 mon, u8 day, u8 week) {RTC_DateTypeDef RTC_DateStruct;RTC_DateStruct.RTC_Year = year;RTC_DateStruct.RTC_Month = mon;RTC_DateStruct.RTC_Date = day;RTC_DateStruct.RTC_WeekDay = week;return RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct); }//RTC初始化 u8 MY_RTC_Init(void) {u16 retry = 0x1fff;RTC_InitTypeDef RTC_InitStruct;//使能PWR時鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能后備寄存器訪問PWR_BackupAccessCmd(ENABLE);//判斷是否第一次初始化if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x8080){//開啟LSERCC_LSEConfig(RCC_LSE_ON);//等待LSE準備就緒while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){retry++;delay_ms(10);}//開始LSE失敗if (0 == retry){return 1;}//設置RTC時鐘為LSERCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//使能RTC時鐘RCC_RTCCLKCmd(ENABLE);//初始化RTCRTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;RTC_InitStruct.RTC_AsynchPrediv = 0x7F;RTC_InitStruct.RTC_SynchPrediv = 0xFF;RTC_Init(&RTC_InitStruct);//設置時間RTC_Set_Time(16, 06, 50, RTC_H12_AM);//設置日期RTC_Set_Date(20, 9, 9, RTC_Weekday_Wednesday);//標記已經初始化RTC_WriteBackupRegister(RTC_BKP_DR0, 0x8080);}return 0; }main.c
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h" #include "usmart.h" #include "lcd.h" #include "rtc.h"//LED狀態設置函數 void led_set(u8 sta) {LED1 = sta; }//函數參數調用測試函數 void test_fun(void(*ledset)(u8), u8 sta) {ledset(sta); }int main(void) { u8 buf[40];u8 t = 0;RTC_TimeTypeDef RTC_TimeStruct;RTC_DateTypeDef RTC_DateStruct;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置系統中斷優先級分組2delay_init(168);uart_init(115200);usmart_dev.init(84);LED_Init();LCD_Init();//RTC初始化MY_RTC_Init();POINT_COLOR = RED;LCD_ShowString(30,50,200,16,16,"Explorer STM32F4"); LCD_ShowString(30,70,200,16,16,"USMART TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2020/09/09"); while(1){t++;//每隔100ms更新顯示if (0 == t % 10){RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);sprintf((char*)buf, "Time: %02d:%02d:%02d", RTC_TimeStruct.RTC_Hours, RTC_TimeStruct.RTC_Minutes, RTC_TimeStruct.RTC_Seconds);LCD_ShowString(30, 140, 210, 16, 16, buf);RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);sprintf((char*)buf, "Date: 20%02d-%02d-%02d", RTC_DateStruct.RTC_Year, RTC_DateStruct.RTC_Month, RTC_DateStruct.RTC_Date);LCD_ShowString(30, 160, 210, 16, 16, buf);sprintf((char*)buf, "Week: %d", RTC_DateStruct.RTC_WeekDay);LCD_ShowString(30, 180, 210, 16, 16, buf); }if (0 == t % 20){LED1 = !LED1;}//睡眠10毫秒delay_ms(10);} }05. 設置鬧鐘中斷示例
//設置鬧鐘時間(按星期鬧鈴,24小時制) //week:星期幾(1~7) @ref RTC_Alarm_Definitions //hour,min,sec:小時,分鐘,秒鐘 void RTC_Set_AlarmA(u8 week,u8 hour,u8 min,u8 sec) {RTC_TimeTypeDef RTC_TimeStruct;RTC_AlarmTypeDef RTC_AlarmStruct;EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;//關閉鬧鐘ARTC_AlarmCmd(RTC_Alarm_A, DISABLE);//設置鬧鐘參數RTC_TimeStruct.RTC_H12 = RTC_H12_AM;RTC_TimeStruct.RTC_Hours = hour;RTC_TimeStruct.RTC_Minutes = min;RTC_TimeStruct.RTC_Seconds = sec;RTC_AlarmStruct.RTC_AlarmTime = RTC_TimeStruct;RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_None;RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay;RTC_AlarmStruct.RTC_AlarmDateWeekDay = week;RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStruct);//清除鬧鐘A的中斷標志RTC_ClearITPendingBit(RTC_IT_ALRA);//清除中斷線17上的中斷標志EXTI_ClearITPendingBit(EXTI_Line17);//開啟鬧鐘A中斷RTC_ITConfig(RTC_IT_ALRA, ENABLE);//開啟鬧鐘RTC_AlarmCmd(RTC_Alarm_A, ENABLE);//初始化中斷EXTI_InitStruct.EXTI_Line = EXTI_Line17;EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_Init(&EXTI_InitStruct);//初始化中斷優先級NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2;NVIC_Init(&NVIC_InitStruct); }//鬧鐘中斷處理函數 void RTC_Alarm_IRQHandler(void) {if (RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET){RTC_ClearFlag(RTC_FLAG_ALRAF);printf("ALARM A!\r\n");}//清中斷EXTI_ClearITPendingBit(EXTI_Line17); }06. 設置喚醒中斷示例
//周期性喚醒定時器設置 /*wksel: @ref RTC_Wakeup_Timer_Definitions #define RTC_WakeUpClock_RTCCLK_Div16 ((uint32_t)0x00000000) #define RTC_WakeUpClock_RTCCLK_Div8 ((uint32_t)0x00000001) #define RTC_WakeUpClok_RTCCLK_Div4 ((uint32_t)0x00000002) #define RTC_WakeUpClock_RTCCLK_Div2 ((uint32_t)0x00000003) #define RTC_WakeUpClock_CK_SPRE_16bits ((uint32_t)0x00000004) #define RTC_WakeUpClock_CK_SPRE_17bits ((uint32_t)0x00000006) */ //cnt:自動重裝載值.減到0,產生中斷. void RTC_Set_WakeUp(u32 wksel,u16 cnt) {EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;//關閉WakeUPRTC_WakeUpCmd(DISABLE);//配置WakeUP時鐘分頻系數或者來源RTC_WakeUpClockConfig(wksel);//設置WakeUP自動裝載值RTC_SetWakeUpCounter(cnt);//清除中斷標志RTC_ClearITPendingBit(RTC_IT_WUT);//清除中斷線17上的中斷標志EXTI_ClearITPendingBit(EXTI_Line22);//開啟WakeUP中斷RTC_ITConfig(RTC_IT_WUT, ENABLE);//使能WakeUpRTC_WakeUpCmd(ENABLE);//初始化中斷EXTI_InitStruct.EXTI_Line = EXTI_Line22;EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_Init(&EXTI_InitStruct);//初始化中斷優先級NVIC_InitStruct.NVIC_IRQChannel = RTC_WKUP_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2;NVIC_Init(&NVIC_InitStruct);}//喚醒中斷處理函數 void RTC_WKUP_IRQHandler(void) {if (RTC_GetFlagStatus(RTC_FLAG_WUTF) == SET){RTC_ClearFlag(RTC_FLAG_WUTF);LED2 = !LED2;}//清中斷EXTI_ClearITPendingBit(EXTI_Line22); }07. 附錄
7.1 【STM32】STM32系列教程匯總
網址:【STM32】STM32系列教程匯總
08. 聲明
該教程參考了正點原子的《STM32 F4 開發指南》
總結
以上是生活随笔為你收集整理的【STM32】RTC程序示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【STM32】RTC相关函数和类型
- 下一篇: 【STM32】随机数发生器详解