- //程序中的時間(normal time)是根據國際標準時間戳轉換為東八區的北京時間(NORMALTIME)。
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- #ifndef _RTC_H_
- #define _RTC_H_
- #include "driver_about.h"
- #include <time.h>
- #include <stdio.h>
- #include <string.h>
- typedef struct tm NORMALTIME;//時間類型;把不是很友好的西方時間表示形式,轉換為我們習慣的表示方式
- //如:1-12月的表示由原來的0-11改為1-12,0表示星期天改為7表示,國際時間改為東八區時間
- typedef time_t TIMESTAMP;//時間戳類型
- void RTC_Init(NORMALTIME t);
- void RTC_Rst(TIMESTAMP ts);//RTC復位
- TIMESTAMP Time_GetTimeStamp(void); //獲取RTC中的時間戳
- void Time_SetTimeStamp(TIMESTAMP ts);//設置RTC中的時間
- NORMALTIME Time_GetTime(void);
- void Time_SetTime(NORMALTIME t);
- #endif
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- #include "Rtc.h"
- /*******************************************************************************
- * Function Name : NVIC_Configuration
- * Description : Configures the RTC.
- * Input : None
- * Output : None
- * Return : None
- * Attention : None
- *******************************************************************************/
- static void RTC_Configuration(void)//RTC的初始化的基本配置(包括RTC的時鐘源選擇和分頻,及秒中斷的使能);為RTC_Init(void)做準備
- {
- /* Enable PWR and BKP clocks */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//開啟PWR和BKP的時鐘
- /* Allow access to BKP Domain */
- PWR_BackupAccessCmd(ENABLE);//允許訪問BKP,對PWR_CR中的DBP位進行寫1,以允許對BKP和RTC模塊的操作
- /* Reset Backup Domain */
- BKP_DeInit();//復位BKP
- /* Enable LSE */
- RCC_LSEConfig(RCC_LSE_ON); //外部低速時鐘使能
- /* Wait till LSE is ready */
- while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}//等待時鐘準備好
- /* Select LSE as RTC Clock Source */
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //選擇外部低速時鐘外RTC的時鐘源
- /* Enable RTC Clock */
- RCC_RTCCLKCmd(ENABLE); //使能RTC的時鐘 ,是通過對RCC_BDCR中的RTCEN位的操作來開啟RTC的時鐘的
- /* Wait for RTC registers synchronization */
- RTC_WaitForSynchro();
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- /* Enable the RTC Second */
- //RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC的秒中斷
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- /* Set RTC prescaler: set RTC period to 1sec */
- RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) *///RTC為32767+1分頻,每秒一次溢出中斷
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- }
- /*******************************************************************************
- * Function Name : NVIC_Configuration
- * Description : Configures the nested vectored interrupt controller.
- * Input : None
- * Output : None
- * Return : None
- * Attention : None
- *******************************************************************************/
- // void NVIC_Configuration(void) //RTC模塊的中斷配置
- // {
- // NVIC_InitTypeDef NVIC_InitStructure;
- // /* Configure one bit for preemption priority */
- // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
- // /* Enable the RTC Interrupt */
- // NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
- // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- // NVIC_Init(&NVIC_InitStructure);
- // }
- ///////////////////時間形式的轉換/////////////////////////////////
- TIMESTAMP TimeConv_Nomal2Stamp(NORMALTIME t)//正常(北京)時間轉換為時間戳
- {
- t.tm_year-=1900;//雖然時間戳是以1970年(正數部分0x00000000)開始計時,但時間轉換是轉成1900年(負數第32bit決定)的相對時間
- t.tm_mon -=1;
- if(t.tm_wday>=7)
- t.tm_wday=0;
- t.tm_hour-=8;
- return mktime(&t);
- }
- NORMALTIME TimeConv_Stamp2Nomal(TIMESTAMP ts)//時間戳轉換為正常(北京)時間
- {
- NORMALTIME *pt,t;
- pt = localtime(&ts);//函數為把時間戳轉換成從1900開始的相對時間值,需要加上開始的時間
- t=*pt;
- t.tm_year+=1900;
- t.tm_mon +=1;
- if(t.tm_wday==0)
- t.tm_wday=7;
- t.tm_hour+=8;//轉為北京時間
- return t;
- }
- //////////////////時間戳方式獲取時間和設置時間///////////////////////
- TIMESTAMP Time_GetTimeStamp(void) //獲取RTC中的時間戳
- {
- return (TIMESTAMP)RTC_GetCounter();
- }
- void Time_SetTimeStamp(TIMESTAMP ts)//設置RTC中的時間(時間戳的形式)
- {
- RTC_Configuration();
- RTC_WaitForLastTask();
- RTC_SetCounter((u32)ts);
- BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//把0xA5A5寫入BKP_DR1寄存器中
- RTC_WaitForLastTask();
- }
- /////////////////常規時間方式獲取和設置時間/////////////////////////
- NORMALTIME Time_GetTime(void) //獲取正常(北京)時間
- {
- return TimeConv_Stamp2Nomal((TIMESTAMP)RTC_GetCounter());
- }
- void Time_SetTime(NORMALTIME t)//設置正常(北京)時間
- {
- Time_SetTimeStamp(TimeConv_Nomal2Stamp(t));
- }
- //////////////////RTC模塊復位//////////////////////////////////////
- void RTC_Rst(TIMESTAMP ts)//RTC復位
- {
- RTC_Configuration();//如果沒有配置,則進行相應的初始化基本配置
- Time_SetTimeStamp(ts);
- /* Adjust time by values entred by the user on the hyperterminal */
- BKP_WriteBackupRegister(BKP_DR1, 0x0000);//把0x0000寫入BKP_DR1寄存器中
- }
- // RTC_EnterConfigMode();
- // /* Set RTC COUNTER MSB word */
- // RTC->CNTH = CounterValue >> 16;
- // /* Set RTC COUNTER LSB word */
- // RTC->CNTL = (CounterValue & RTC_LSB_MASK);
- // RTC_ExitConfigMode();
- /*******************************************************************************
- * Function Name : RTC_Init
- * Description : RTC Initialization
- *******************************************************************************/
- void RTC_Init(NORMALTIME t)//RTC初始化
- {
- if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)//判斷RTC模塊是否進行了配置
- {
- RTC_Configuration();//如果沒有配置,則進行相應的初始化基本配置
- Time_SetTime(t);//寫入最初的RTC時間
- /* Adjust time by values entred by the user on the hyperterminal */
- BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//把0xA5A5寫入BKP_DR1寄存器中
- }
- /*
- else
- {
- //Check if the Power On Reset flag is set
- if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)//判斷是否發生了電源上電復位
- {
- printf("Power On Reset occurred....\r\n");
- }
- // Check if the Pin Reset flag is set
- else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)//判斷是否發生了引腳復位
- {
- printf("External Reset occurred....\r\n");
- }
- printf("No need to configure RTC....\r\n");
- // Wait for RTC registers synchronization
- RTC_WaitForSynchro();
- // Enable the RTC Second
- RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中斷
- // Wait until last write operation on RTC registers has finished
- RTC_WaitForLastTask();
- }
- // NVIC configuration
- NVIC_Configuration();//RTC的嵌套向量中斷配置
- #ifdef RTCClockOutput_Enable
- // Enable PWR and BKP clocks
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
- // Allow access to BKP Domain
- PWR_BackupAccessCmd(ENABLE);
- // Disable the Tamper Pin
- BKP_TamperPinCmd(DISABLE); // To output RTCCLK/64 on Tamper pin, the tamper functionality must be disabled
- // Enable RTC Clock Output on Tamper Pin
- BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
- #endif
- // Clear reset flags
- RCC_ClearFlag(); //清除各種復位標志*/
- return;
- }
- // /*******************************************************************************
- // * Function Name : Time_GetCalendarTime
- // * Description : 從RTC取當前時間的日歷時間(struct tm)
- // * Input : None
- // * Output : None
- // * Return : struct tm
- // * Attention : None
- // *******************************************************************************/
- // struct tm Time_GetCalendarTime(void) //獲取RTC中的日歷時間
- // {
- // time_t t_t;
- // struct tm t_tm;
- // t_t = (time_t)RTC_GetCounter();
- // t_tm = Time_ConvUnixToCalendar(t_t);
- // return t_tm;
- // }
- /******************************************************************************************************************************
- 以下函數為設置RTC時鐘
- ******************************************************************************************************************************/
- // /*******************************************************************************
- // * Function Name : Time_SetCalendarTime
- // * Description : 將給定的Calendar格式時間轉換成UNIX時間戳寫入RTC
- // * Input : - t: struct tm
- // * Output : None
- // * Return : None
- // * Attention : None
- // *******************************************************************************/
- // void Time_SetCalendarTime(struct tm t)//以日歷的形式設置RTC中的時間
- // {
- // Time_SetUnixTime(Time_ConvCalendarToUnix(t));
- // return;
- // }
- // /******************************************************************************************************************************
- // 以下兩個函數為時間戳和日歷時間之間的轉換(日歷時間為從1900-1-1開始的)
- // ******************************************************************************************************************************/
- // /*******************************************************************************
- // * Function Name : Time_ConvUnixToCalendar
- // * Description : 轉換UNIX時間戳為日歷時間
- // * Input : - t: 當前時間的UNIX時間戳
- // * Output : None
- // * Return : struct tm
- // * Attention : None
- // *******************************************************************************/
- // struct tm Time_ConvUnixToCalendar(time_t t)//把時間戳轉換為日歷時間(前提是時間戳開始時間和日歷開始計算的時間相同,都是從1900年開始計算)
- // {
- // struct tm *t_tm;
- // t_tm = localtime(&t);//t_tm = localtime(&t);函數為把時間戳轉換成從1900開始的相對時間值,需要加上開始的時間
- // t_tm->tm_year += 1900;/* localtime轉換結果的tm_year是相對值,需要轉成絕對值 */
- //
- // return *t_tm;
- // }
- // /*******************************************************************************
- // * Function Name : Time_ConvCalendarToUnix
- // * Description : 寫入RTC時鐘當前時間
- // * Input : - t: struct tm
- // * Output : None
- // * Return : time_t
- // * Attention : None
- // *******************************************************************************/
- // time_t Time_ConvCalendarToUnix(struct tm t)//把日歷時間轉換為時間戳
- // {
- // t.tm_year -= 1900; /* 外部tm結構體存儲的年份為2008格式*/
- // /* 而time.h中定義的年份格式為1900年開始的年份 */
- // /* 所以,在日期轉換時要考慮到這個因素。*/
- // return mktime(&t);
- // }
-
- // /*******************************************************************************
- // * Function Name : Time_Regulate
- // * Description : None
- // * Input : None
- // * Output : None
- // * Return : None
- // * Attention : None
- // *******************************************************************************/
- // void Time_Regulate(void)
- // {
- // struct tm time;
- // memset(&time, 0 , sizeof(time) );/* 清空結構體 */
- //
- // time.tm_year =2012;//設定年1970-2037
- //
- // time.tm_mon=1-1;//設定月(1-12)-1
- // time.tm_mday = 1;//設定日1-31
- // time.tm_hour =1;//設定小時0-23
- // time.tm_min = 1;//設定分0-59
- // time.tm_sec =1;//設定秒0-59
- // /* Return the value to store in RTC counter register */
- // Time_SetCalendarTime(time);//根據以上設定對RTC進行設置
- // }
- // /*******************************************************************************
- // * 本文件實現基于RTC的日期功能,提供年月日的讀寫。(基于ANSI-C的time.h)
- // *
- // * RTC中保存的時間格式,是UNIX時間戳格式的。即一個32bit的time_t變量(實為u32)
- // *
- // * ANSI-C的標準庫中,提供了兩種表示時間的數據 型:
- // * time_t: UNIX時間戳(從19xx-1-1起到某時間經過的秒數)
- // * typedef unsigned int time_t;
- // *
- // * struct tm:Calendar格式(年月日形式)
- // * tm結構如下:
- // * struct tm {
- // * int tm_sec; // 秒 seconds after the minute, 0 to 60(0 - 60 allows for the occasional leap second)
- // * int tm_min; // 分 minutes after the hour, 0 to 59
- // * int tm_hour; // 時 hours since midnight, 0 to 23
- // * int tm_mday; // 日 day of the month, 1 to 31
- // * int tm_mon; // 月 months since January, 0 to 11
- // * int tm_year; // 年 years since 1900
- // * int tm_wday; // 星期 days since Sunday, 0 to 6
- // * int tm_yday; // 從元旦起的天數 days since January 1, 0 to 365
- // * int tm_isdst; // 夏令時??Daylight Savings Time flag
- // * ...
- // * }
- // * 其中wday,yday可以自動產生,軟件直接讀取
- // * mon的取值為0-11
- // ****注意***:
- // *tm_year:在time.h庫中定義為1900年起的年份,即2008年應表示為2008-1900=108
- // * 這種表示方法對用戶來說不是十分友好,與現實有較大差異。
- // * 所以在本文件中,屏蔽了這種差異。
- // * 即外部調用本文件的函數時,tm結構體類型的日期,tm_year即為2008
- // * 注意:若要調用系統庫time.c中的函數,需要自行將tm_year-=1900
- // *
- // * 成員函數說明:
- // * struct tm Time_ConvUnixToCalendar(time_t t);
- // * 輸入一個Unix時間戳(time_t),返回Calendar格式日期
- // * time_t Time_ConvCalendarToUnix(struct tm t);
- // * 輸入一個Calendar格式日期,返回Unix時間戳(time_t)
- // * time_t Time_GetUnixTime(void);
- // * 從RTC取當前時間的Unix時間戳值
- // * struct tm Time_GetCalendarTime(void);
- // * 從RTC取當前時間的日歷時間
- // * void Time_SetUnixTime(time_t);
- // * 輸入UNIX時間戳格式時間,設置為當前RTC時間
- // * void Time_SetCalendarTime(struct tm t);
- // * 輸入Calendar格式時間,設置為當前RTC時間
- // *
- // * 外部調用實例:
- // * 定義一個Calendar格式的日期變量:
- // * struct tm now;
- // * now.tm_year = 2008;
- // * now.tm_mon = 11;//12月
- // * now.tm_mday = 20;
- // * now.tm_hour = 20;
- // * now.tm_min = 12;
- // * now.tm_sec = 30;
- // *
- // * 獲取當前日期時間:
- // * tm_now = Time_GetCalendarTime();
- // * 然后可以直接讀tm_now.tm_wday獲取星期數
- // *
- // * 設置時間:
- // * Step1. tm_now.xxx = xxxxxxxxx;
- // * Step2. Time_SetCalendarTime(tm_now);
- // *
- // * 計算兩個時間的差
- // * struct tm t1,t2;
- // * t1_t = Time_ConvCalendarToUnix(t1);
- // * t2_t = Time_ConvCalendarToUnix(t2);
- // * dt = t1_t - t2_t;
- // * dt就是兩個時間差的秒數
- // * dt_tm = mktime(dt);//注意dt的年份匹配,ansi庫中函數為相對年份,注意超限
- // * 另可以參考相關資料,調用ansi-c庫的格式化輸出等功能,ctime,strftime等
- // *
- //*******************************************************************************/
復制代碼
|