大家好,我是陳濱。本人學STM32也有幾個月的時間,從對ARM望而生畏到現在會開發STM32程序,途中付出也不少,很多人看到ARM處理器那些復雜的寄存器,都望而卻步;但是本人沒有這樣子,反而越復雜越想征服它!在開發的過程中,本人積累了不少經驗,這個就有其中的RTC。這不,最近在開發3264萬年歷就積累了這個知識。大家都知道STM32F103系列的RTC只是一個秒計數器,沒有提供真正的年月日功能,網上很多資料都把這個計數器進行60進制處理得到時間,但是這個方法效率很低不說,閏年閏月還不好處理;這個是一個問題,而且在設置的時候,處理也是一個問題!經過本人苦苦的研究發現:KEIL已經幫我們完成這個問題。KEIL里面有一個頭文件,叫time.h,專門針對32位處理器處理實時時鐘功能,該文件支持把計數器直接轉換成時間信息,也支持設置時間信息,還支持計算兩地的時間差,并且自動計算出星期信息,支持從1970年到2108年的計算,更有趣的是,該文件還支持把計數器的值直接打印成字符串,下面是本人將這個功能直接打印在液晶屏的結果:

下面本人將按實際教大家來寫這個程序:
在該頭文件中,定義了一個結構體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 */
union { /* ABI-required extra fields, in a variety of types */
struct {
int __extra_1, __extra_2;
};
struct {
long __extra_1_long, __extra_2_long;
};
struct {
char *__extra_1_cptr, *__extra_2_cptr;
};
struct {
void *__extra_1_vptr, *__extra_2_vptr;
};
};
};
從以上的結構體注釋可以看出(雖然本人的英語很差,但還是看得懂):在結構體中聲明了很多變量,其中的tm_sec就是秒,范圍是0-59;還有tm_min,自然就是分鐘,下面的tm_hour不用我說了吧?到了tm_yday這個是今年到現在的天數,可以不用管,下面是tm_isdst是設置保存標志,一般也不用管。那么怎么從這個結構體得到時間信息或者是設置時間呢?在這個頭文件中,定義了一個函數:
extern _ARMABI struct tm *localtime(const time_t * /*timer*/) __attribute__((__nonnull__(1)));
這個函數的功能是輸入一個32位秒計算值,輸出一個時間信息結構體,好,現在我來寫這個程序:
首先創建一個函數,名字就叫Get_time吧:
void Get_time()
{
u32 temp;
u8 sec,min,hour,day,week,month,year; //定義時間信息變量
struct tm *loca; //定義一個結構體指針
temp=RTC->CNTH; //從STM32的RTC中取出高16數據賦值給臨時變量temp
temp<<=16; //左移16位把數據移向高16位
time_count=temp|RTC->CNTL; //從STM32的RTC中讀取低16數據與高16數據相或得到一個32位數據,這個關系數學計算,本人的數學還可以,哈哈
loca=localtime(&time_count); 將這個32位數據地址賦值給locatime的參數入口,這個時候這個函數開始工作,接下來可以讀取信息了
sec=loca->tm_sec; ///取出秒信息,這個關系到C語言的指針知識,如果你看不懂,再去學習
min=loca->tm_min; //取出分鐘,下面以此類推
hour=loca->tm_hour;
day=loca->tm_mday;
week=loca->wday;
month=loca->tm_mon;
year=loca->tm_year;
}
以上是得到時間日期的信息,頭文件定義了下面的函數:
extern _ARMABI time_t mktime(struct tm * /*timeptr*/) __attribute__((__nonnull__(1)));
這個函數的功能是輸入一個結構體時間信息,輸出一個32位計數值,下面本人再寫個程序,將設置的時間日期信息寫入RTC:
void Set_time(u8 sec,u8 s_min,u8 s_hour,u8 s_day,u8 s_month,u16 s_year)
{
struct tm Rtc; //定義一個時間結構體
u32 tim;
Rtc.tm_sec=sec; //將參數的值賦值給設置值
Rtc.tm_min=s_min;
Rtc.tm_hour=s_hour;
Rtc.tm_mday=s_day;
Rtc.tm_mon=s_month-1; //月份從0-11,填入的是1-12,所以減去1
Rtc.tm_year=s_year-1900; //減去1900年,這個是由keil的函數決定的
Rtc.tm_isdst=-1;
tim=mktime(&Rtc);
PWR->CR=PWR_CR_DBP; //取消后備保護
RTC->CRL=RTC_CRL_CNF; //進入STM32配置模式
RTC->CNTH=tim>>16;
RTC->CNTL=tim&0xffff;
RTC->CRL&=0x2f; //退出配置模式
while(!(RTC->CRL&RTC_CRL_RTOFF)); //等待寫入完成
PWR->CR=0; //打開保護
}
注意:星期是無需設置的,該函數自動會計算生成!
以上是讀出和寫入的功能,文件中還定義了另外一個函數:
extern _ARMABI unsigned char *asctime(const struct tm * /*timeptr*/) __attribute__((__nonnull__(1)));
這個就是本文開頭的功能了,就是輸入一個時間結構體,輸出字符串信息,這個不難了吧?大家自己研究。
|