一、概述
1、實時時鐘定義
實時時鐘(RTC)是一個獨立的BCD定時器/計數(shù)器。RTC提供一個日歷時鐘和兩個可編程鬧鐘中斷,以及一個具有中斷功能的周期性可編程喚醒標志。RTC還包含用于管理低功耗模式的自動喚醒單元。
兩個32位寄存器包含二進碼十進位格式(BCD)的秒、分鐘、小時(12或24小時制)、星期幾、日期、月份和年份。此外,還可以提供二進制格式的亞秒值。
系統(tǒng)可以自動將月份的天數(shù)補償位28、29(閏年),30和31天。并且還可以進行夏令時的補償。
其他32位寄存器還包括可編程的鬧鐘亞秒、秒、分鐘、小時、星期幾和日期。此外,還可以使用數(shù)字校準功能對晶振精度的偏差進行補償。
上電復位后,所有RTC寄存器都會受到保護,以防止可能的非正常寫訪問。 無論器件狀態(tài)如何(運行模式、低功耗模式或處于復位狀態(tài)),只要電源電壓保持在工作范圍內(nèi),RTC使不會停止工作。
2、實時時鐘主要特性
RTC的主要特性如下: - 包含亞秒、秒、分鐘、小時(12/24小時制)、星期幾、日期、月份和年份的日期。
- 軟件可編程的夏令時補償。
- 兩個具有中斷功能的可編程鬧鐘。可通過任意日歷字段的組合驅(qū)動鬧鐘。
- 自動喚醒單元,可周期性地生成標志以觸發(fā)自動喚醒中斷。
- 參考時鐘檢測:可使用更加精確的第二時鐘源(50Hz或60Hz)來提高日歷的精確度。
- 利用亞秒級移位特性與外部時鐘實現(xiàn)精確同步。
- 可屏蔽中斷/事件:
— 鬧鐘A — 鬧鐘B — 喚醒中斷 — 時間戳 — 入侵檢測 - 數(shù)字校準電路(周期性計數(shù)器調(diào)整)。
— 精度為5ppm。 — 精度為0.95ppm, 在數(shù)秒鐘的校準窗口中獲得。 — 2個帶可配置過濾器和內(nèi)部上拉的入侵事件。
— RTC_CALIB:512Hz或1Hz時鐘輸出(LSE頻率為32.768kHZ)。可通過將RTC_CR寄存器中的COE【23】位置1來使能此輸出。該輸出可連接到器件RTC_AF1功能。 — RTC_ALARM(鬧鐘A、鬧鐘B或喚醒)。可通過配置RTC_CR寄存器的OSEL【1:0】位選擇此輸出。該輸出可連接到器件RTC_AF1功能。 — RTC_TS:時間戳事件檢測。該輸入可連接到器件RTC_AF1和RTC_AF2功能。 — RTC_TAMP1:TAMPER1 事件檢測。該輸入可連接到器件RTC_AF1和RTC_AF2功能。 — RTC_TAMP2:TAMPER2 事件檢測。 — RTC_REFIN:參考時鐘輸入(通常為市電,50Hz或60Hz)。 二、硬件電路 1、時鐘源 iCore3異構(gòu)雙核心工控板采用32.768K無源晶體為系統(tǒng)提供RTC實時時鐘,其電路連接圖如下所示。32.768KHz外部無源晶體連接 OSC32_IN和OSC32_OUT兩引腳之間,為獲得穩(wěn)定的頻率必須加兩個電容構(gòu)成外部震蕩電路。 圖10_0 外部振蕩電路 2、備用電源 RTC實時時鐘在iCore3電路中具有備用電源,時刻保證時鐘通電。 圖10_1 備用電池電路 三、實驗原理 STM32的實時時鐘(RTC)是一個獨立的定時器,有一組連續(xù)計數(shù)的計時器,通過軟件來對其進行相關(guān)的配置,可以提供時鐘功能,通過修改計數(shù)器的值可以調(diào)整時鐘,最終通過串口在終端顯示時間。 四、源代碼 1、主函數(shù) - /*
- * Name : main
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * --------------------
- * Rev : 0.00
- * Date : 11/23/2015
- *
- * create.
- * --------------------
- */
- int main(void)
- {
- int i;
- RTC_TimeTypeDef rtc_time;
- RTC_DateTypeDef rtc_date;
- int second_bak = 0;
- led.initialize();
- LED_RED_ON;
- rtc.initialize();
- usart4.initialize(115200);
- usart4.printf("\x0c"); //清屏
- usart4.printf("\033[1;32;40m"); //設(shè)置字體終端為綠色
- usart4.printf("\r\n\r\nhello! I am iCore3!\r\n\r\n\r\n");
- while(1){
- for(i = 0;i < 1000000;i++);
- //讀取RTC日期和時間
- RTC_GetTime(RTC_Format_BIN,&rtc_time);
- RTC_GetDate(RTC_Format_BIN,&rtc_date);
- //當秒數(shù)據(jù)與備份不一致時,向終端打印時間/日期
- if(second_bak != rtc_time.RTC_Seconds){
- usart4.printf(" %02d:%02d:%02d ",rtc_time.RTC_Hours,rtc_time.RTC_Minutes,rtc_time.RTC_Seconds);
- usart4.printf("20%02d-%02d-%02d \r",rtc_date.RTC_Year,rtc_date.RTC_Month,rtc_date.RTC_Date);\
- second_bak = rtc_time.RTC_Seconds; //秒數(shù)據(jù)備份
- }
- }
- }
復制代碼2、RTC初始化 - /*
- * Name : initialize
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * -------------------
- * Rev : 0.00
- * Date : 11/23/2015
- *
- * create.
- * -------------------
- */
- static int initialize(void)
- {
- //判斷讀到的備份寄存器的值與寫入的值是否一樣
- if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2){
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
- //使能PWR時鐘
- PWR_BackupAccessCmd(ENABLE);
- RCC_BackupResetCmd(ENABLE);
- RCC_BackupResetCmd(DISABLE);
- RCC_LSEConfig(RCC_LSE_ON); //LSE 開啟
- while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) ==RESET); //檢查指定的RCC標志位設(shè)置與否,等待低速晶振就緒
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //設(shè)置RTC時鐘(RTCCLK),選擇LSE作為RTC時鐘
- RCC_RTCCLKCmd(ENABLE); //使能RTC時鐘
- RTC_WaitForSynchro();
- //等待APB1和RTC等時鐘同步
- rtc_set_time(13,57,12,RTC_H12_PM); //設(shè)置時間
- rtc_set_date(15,11,28,6); //設(shè)置日期
- RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2); //向備份寄存器中寫入數(shù)值
- }
- return 0;
- }
- /*
- * Name : initialize
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * -------------------
- * Rev : 0.00
- * Date : 11/23/2015
- *
- * create.
- * -------------------
- */
- static int rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec,unsigned char ampm)
- {
- //設(shè)置時間
- RTC_TimeTypeDef RTC_TimeTypeInitStructure;
- RTC_TimeTypeInitStructure.RTC_Hours=hour;
- RTC_TimeTypeInitStructure.RTC_Minutes=min;
- RTC_TimeTypeInitStructure.RTC_Seconds=sec;
- RTC_TimeTypeInitStructure.RTC_H12=ampm;
- RTC_SetTime(RTC_Format_BIN,&RTC_TimeTypeInitStructure);
- return 0;
- }
復制代碼3、RTC配置介紹 - static int initialize(void)
- {
- //判斷讀到的備份寄存器的值與寫入的值是否一樣
- if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2){
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
- //使能PWR時鐘
- PWR_BackupAccessCmd(ENABLE);
- RCC_BackupResetCmd(ENABLE);
- RCC_BackupResetCmd(DISABLE);
- RCC_LSEConfig(RCC_LSE_ON); //LSE 開啟
- while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) ==RESET); //檢查指定的RCC標志位設(shè)置與否,等待低速晶振就緒
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //設(shè)置RTC時鐘(RTCCLK),選擇LSE作為RTC時鐘
- RCC_RTCCLKCmd(ENABLE); //使能RTC時鐘
- RTC_WaitForSynchro();
- //等待APB1和RTC等時鐘同步
- rtc_set_time(13,57,12,RTC_H12_PM); //設(shè)置時間
- rtc_set_date(15,11,28,6); //設(shè)置日期
- RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2); //向備份寄存器中寫入數(shù)值
- }
- return 0;
- }
- static int rtc_set_date(unsigned char year,unsigned char month,unsigned char date,unsigned char week)
- {
- //設(shè)置日期
- RTC_DateTypeDef RTC_DateTypeInitStructure;
- RTC_DateTypeInitStructure.RTC_Date=date;
- RTC_DateTypeInitStructure.RTC_Month=month;
- RTC_DateTypeInitStructure.RTC_WeekDay=week;
- RTC_DateTypeInitStructure.RTC_Year=year;
- RTC_SetDate(RTC_Format_BIN,&RTC_DateTypeInitStructure);
- return 0;
- }
復制代碼4、結(jié)構(gòu)體介紹 - /**
- * @brief RTC Init structures definition
- */
- typedef struct
- {
- uint32_t RTC_HourFormat; 指定RTC小時格式,
- 這個參數(shù)可以是@ref rtc_hour_format的值。
- uint32_t RTC_AsynchPrediv; 指定RTC異步預分值,
- 此參數(shù)必須設(shè)置為低于0x7F的值。
- uint32_t RTC_SynchPrediv; 指定RTC同步預分值,
- 此參數(shù)必須設(shè)置為低于0x7FFF的值。
- }RTC_InitTypeDef;
- /**
- * @brief RTC Time structure definition
- */
- typedef struct
- {
- uint8_t RTC_Hours; 指定RTC時間小時,此參數(shù)必須設(shè)置為0-12范圍內(nèi)的值。如果選擇RTC_HourFormat_12,則為0-23。該RTC_HourFormat_24被選中。
- uint8_t RTC_Minutes; 指定RTC時間分鐘,
- 此參數(shù)必須設(shè)置為0-59范圍內(nèi)值。
- uint8_t RTC_Seconds; 指定RTC時間秒,
- 此參數(shù)必須設(shè)置為0-59范圍內(nèi)的值。
- uint8_t RTC_H12; 指定RTC AM/PM時間,
- 這個參數(shù)可以是@ref rtc_am_pm_definition的值。
- }RTC_TimeTypeDef;
- /**
- * @brief RTC Date structure definition
- */
- typedef struct
- {
- uint8_t RTC_WeekDay; 指定RTC日期工作日,這個參數(shù)可以是@refrtc_weekday_definition的值。
- uint8_t RTC_Month; 指定RTC日期月(BCD格式),這個參數(shù)可以是@ref rtc_month_date_definition的值。
- uint8_t RTC_Date; 指定RTC日期,此參數(shù)必須設(shè)置為1-31范圍內(nèi)的值。
- uint8_t RTC_Year; 指定RTC日期年,此參數(shù)必須設(shè)置為0-99范圍內(nèi)的值。
- }RTC_DateTypeDef;
- /**
- * @brief RTC Alarm structure definition
- */
- typedef struct
- {
- RTC_TimeTypeDef RTC_AlarmTime; 指定RTC警報時間成員。
- uint32_t RTC_AlarmMask; 指定RTC報警面具,這個參數(shù)可以是@ref rtc_alarmmask_definition 的值。
- uint32_t RTC_AlarmDateWeekDaySel; 指定RTC警報是在日期或工作日,
- 這個參數(shù)可以是@ref rtc_alarmdateweekday_definition的值。
- uint8_t RTC_AlarmDateWeekDay; 指定RTC報警日期/工作日。
- 如果選擇了警報日期,則該參數(shù)。
- 必須設(shè)置為1-31范圍內(nèi)的值。
- 如果選擇了鬧鐘工作日,這個。
- 參數(shù)可以是@ref rtc_weekday_definition的值。
- }RTC_AlarmTypeDef;
復制代碼五、實驗現(xiàn)象 在終端屏幕上可以看到顯示的時間和日期(如下圖所示)。 
圖10_3 實驗現(xiàn)象圖 六、代碼包下載 網(wǎng)盤:https://pan.baidu.com/s/1jHuZcnc
|