RTC實時時鐘簡介
RTC外設(shè)(Real Time Clock)實質(zhì)是一個掉電后還繼續(xù)運(yùn)行的定時器。從定時器的角度,相對于通用定時器Timer外設(shè),它十分簡單,只有很純粹的計時和觸發(fā)中斷的功能,但具備掉電還能繼續(xù)運(yùn)行的特殊功能,可以應(yīng)用在特定場景。這里所說的掉電是指主電源VDD斷開的情況,因此為了RTC外設(shè)掉電繼續(xù)運(yùn)行,必須接上鋰電池通過VBAT引腳供電。當(dāng)主電源VDD有效時,由VDD給RTC外設(shè)供電;而當(dāng)VDD掉電后,由VBAT給RTC外設(shè)供電。但無論由什么電源供電,RTC中的數(shù)據(jù)都保存在屬于RTC的備份域中,若主電源VDD和VBAT都掉電,那么備份域中保存的所有數(shù)據(jù)將丟失。
從RTC的定時器特性來說,它是一個32位的計數(shù)器,只能向上計數(shù)。在相應(yīng)軟件配置下,可提供時鐘日歷的功能,修改計數(shù)器的值可以重新設(shè)置系統(tǒng)當(dāng)前的時間和日期。它使用的時鐘源有三種,分別為高速外部時鐘的128分頻(HSE/128)、低速內(nèi)部時鐘LSI以及低速外部時鐘LSE。在主電源VDD掉電的情況下,HSE和LSI這兩個時鐘來源都會受到影響,沒法保證RTC正常工作,因此RTC一般使用低速外部時鐘LSE供電。在主電源VDD有效的情況下(待機(jī)),RTC還可以配置鬧鐘事件使CKS32退出待機(jī)模式。
RTC框圖結(jié)果分析
RTC由兩個主要部分組成,參見下圖。第一部分(背景灰色區(qū)域)用來和APB1總線相連,屬于備份域,在VDD掉電時可在VBAT的驅(qū)動下繼續(xù)運(yùn)行。這部分僅包括RTC的分頻器,計數(shù)器和鬧鐘控制器。若VDD電源有效,RTC可以觸發(fā)RTC_Second(秒中斷)、RTC_Overflow(溢出事件)和RTC_Alarm(鬧鐘中斷)。此單元還包含一組16位寄存器,可通過APB1總線對其進(jìn)行讀寫操作。APB1接口由APB1總線時鐘驅(qū)動,用來與APB1總線連接。
另一部分(RTC核心)由一組可編程計數(shù)器組成,分成兩個主要模塊。第一個模塊是RTC的預(yù)分頻模塊,它可編程產(chǎn)生最長為1秒的RTC時間基準(zhǔn)TR_CLK。RTC的預(yù)分頻模塊包含了一個20位的可編程分頻器(RTC 預(yù)分頻器)。如果在RTC_CR寄存器中設(shè)置了相應(yīng)的允許位,則在每個TR_CLK周期中RTC產(chǎn)生一個中斷(秒中斷)。第二個模塊是一個32位的可編程計數(shù)器,可被初始化為當(dāng)前的系統(tǒng)時間,按秒鐘計算,可以記錄4294967296秒,約合136年左右,作為一般應(yīng)用已經(jīng)足夠。RTC還有一個鬧鐘寄存器RTC_ALR,用于產(chǎn)生鬧鐘。系統(tǒng)時間按TR_CLK周期累加并與存儲在RTC_ALR寄存器中的可編程時間相比較,如果RTC_CR控制寄存器中設(shè)置了相應(yīng)允許位,比較匹配時將產(chǎn)生一個鬧鐘中斷。
圖1 簡化的RTC框圖
由于備份域的存在,使得RTC內(nèi)核具有了完全獨立于APB1接口的特性,也因此對RTC寄存器的訪問要遵守一定的規(guī)則。系統(tǒng)復(fù)位后,默認(rèn)禁止訪問后備寄存器和RTC,防止對后備區(qū)域BKP的意外寫操作。需要執(zhí)行以下操作使能才可以對后備寄存器和RTC的訪問:(1)設(shè)置RCC_APB1ENR寄存器的PWREN和BKPEN位來使能電源和后備接口時鐘。(2)設(shè)置PWR_CR寄存器的DBP位使能對后備寄存器和RTC的訪問。設(shè)置后備寄存器為可訪問后,在第一次通過APB1接口訪問RTC時,因為時鐘頻率的差異,所以必須等待APB1與RTC外設(shè)同步,確保被讀取出來的RTC寄存器值是正確的。如果內(nèi)核要對RTC寄存器進(jìn)行任何的寫操作,在內(nèi)核發(fā)出寫指令后,RTC模塊在3個RTCCLK時鐘之后才開始正式的寫RTC寄存器操作。由于RTCCLK的頻率比內(nèi)核主頻低得多,所以每次操作后必須要檢查RTC關(guān)閉操作標(biāo)志位RTOFF,當(dāng)這個標(biāo)志被置1時,寫操作才正式完成。當(dāng)然,以上的操作都具有庫函數(shù)來快速實現(xiàn)。
RTC控制相關(guān)庫函數(shù)
標(biāo)準(zhǔn)庫對RTC控制提供了完善的函數(shù),使用它們可以方便地進(jìn)行控制,本小節(jié)對這些內(nèi)容進(jìn)行講解。RTC相關(guān)的庫函數(shù)在文件cks32f10x_rtc.c和cks32f10x_rtc.h文件中。
1、等待時鐘同步和操作完成
RTC區(qū)域的時鐘比APB時鐘慢,訪問前需要進(jìn)行時鐘同步,只要調(diào)用庫函數(shù) RTC_WaitForSynchro即可,而如果修改了RTC的寄存器,又需要調(diào)用RTC_WaitForLastTask函數(shù)確保數(shù)據(jù)已寫入。這兩個庫函數(shù)主要通過while循環(huán)檢測RTC控制寄存器的RSF和RTOFF位實現(xiàn)等待功能。
/**
* @brief 等待RTC寄存器與APB時鐘同步(RTC_CNT, RTC_ALR and RTC_PRL)
* @note 在APB時鐘復(fù)位或停止后,在對RTC寄存器的任何操作前,必須調(diào)用本函數(shù)
* @param None
* @retval None
*/
void RTC_WaitForSynchro(void)
{
RTC->CRL &= (uint16_t)~RTC_FLAG_RSF;//清除RSF寄存器位
while ((RTC->CRL & RTC_FLAG_RSF) == (uint16_t)RESET);//等待RSF寄存器位為SET
}
/**
* @brief 等待上一次對RTC寄存器的操作完成
* @note 修改RTC寄存器后,必須調(diào)用本函數(shù)
* @param None
* @retval None
*/
void RTC_WaitForLastTask(void)
{
while ((RTC->CRL & RTC_FLAG_RTOFF) == (uint16_t)RESET); //等待至 RTOFF 寄存器位為SET
}
2、使能備份域及RTC訪問
默認(rèn)情況下RTC 所屬的備份域禁止訪問,可用庫函數(shù)PWR_BackupAccessCmd使能訪問。
/**
* @brief 使能對RTC和Backup寄存器的訪問
* @param ENABLE 或 DISABLE
* @retval None
*/
void PWR_BackupAccessCmd(FunctionalState NewState)
{
*(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState;
}
該函數(shù)通過PWR_CR寄存器的DBP位使能訪問,使能后才可以訪問RTC相關(guān)的寄存器,然而若希望修改RTC的寄存器,還需要進(jìn)一步調(diào)用RTC_EnterConfigMode使能RTC控制寄存器的CNF位使能寄存器配置。
/**
* @brief 進(jìn)入RTC配置模式
* @param None
* @retval None
*/
void RTC_EnterConfigMode(void)
{
RTC->CRL |= RTC_CRL_CNF;//設(shè)置CNF位進(jìn)入配置模式
}
3、設(shè)置RTC時鐘分頻
選擇RTC使用的時鐘后,可以使用庫函數(shù)RTC_SetPrescaler進(jìn)行分頻,把函數(shù)參數(shù)PrescalerValue寫入到RTC的PRLH和PRLL寄存器,一般會把RTC時鐘分頻得到1Hz時鐘。
/**
* @brief 設(shè)置RTC分頻配置
* @param PrescalerValue:RTC分頻值
* @retval None
*/
void RTC_SetPrescaler(uint32_t PrescalerValue)
{
RTC_EnterConfigMode();
RTC->PRLH = (PrescalerValue & PRLH_MSB_MASK) >> 16; //設(shè)置RTC分頻值的高八位
RTC->PRLL = (PrescalerValue & RTC_LSB_MASK);//設(shè)置RTC分頻值的低八位
RTC_ExitConfigMode();
}
4、設(shè)置RTC計數(shù)器
RTC外設(shè)中最重要的就是計數(shù)器以及鬧鐘寄存器了,它們可以使用RTC_SetCounter、RTC_GetCounter以及RTC_SetAlarm庫函數(shù)操作。利用RTC_SetCounter可以向RTC的計數(shù)器寫入新數(shù)值,通常這些數(shù)值被設(shè)置為時間戳以更新時間。RTC_GetCounter函數(shù)則用于在RTC正常運(yùn)行時獲取當(dāng)前計數(shù)器的值以獲取當(dāng)前時間。RTC_SetAlarm函數(shù)用于配置鬧鐘時間,當(dāng)計數(shù)器的值與鬧鐘寄存器的值相等時,可產(chǎn)生鬧鐘事件或中斷,該事件可以把睡眠、停止和待機(jī)模式的芯片喚醒。
/**
* @brief 設(shè)置RTC計數(shù)器的值
* @param CounterValue:要設(shè)置的RTC計數(shù)值
* @retval None
*/
void RTC_SetCounter(uint32_t CounterValue)
{
RTC_EnterConfigMode();
RTC->CNTH = CounterValue >> 16;//設(shè)置RTC計數(shù)值的高八位
RTC->CNTL = (CounterValue & RTC_LSB_MASK); //設(shè)置RTC計數(shù)值的低八位
RTC_ExitConfigMode();
}
/**
* @brief 獲取RTC計數(shù)器的值
* @param None
* @retval 返回RTC計數(shù)器的值
*/
uint32_t RTC_GetCounter(void)
{
uint16_t tmp = 0;
tmp = RTC->CNTL;
return (((uint32_t)RTC->CNTH << 16 ) | tmp) ;
}
/**
* @brief 設(shè)置RTC鬧鐘的值
* @param AlarmValue:要設(shè)置的RTC鬧鐘值
* @retval None
*/
void RTC_SetAlarm(uint32_t AlarmValue)
{
RTC_EnterConfigMode();
RTC->ALRH = AlarmValue >> 16;//設(shè)置RTC鬧鐘的高八位
RTC->ALRL = (AlarmValue & RTC_LSB_MASK); //設(shè)置RTC鬧鐘的低八位
RTC_ExitConfigMode();
}
UNIX時間戳
在使用RTC外設(shè)前,還需要引入UNIX時間戳的概念。如果從現(xiàn)在起,把計數(shù)器RTC_CNT的計數(shù)值置0,然后每秒加1,RTC_CNT什么時候會溢出呢?由于RTC_CNT是32位寄存器,可存儲的最大值為(232-1),這樣計時的話,在232秒后溢出,N=232/365/24/60/60≈136年,即它將在今后136年時溢出。
假如某個時刻讀取到計數(shù)器的數(shù)值為X=60*60*24*2,即兩天時間的秒數(shù),而假設(shè)又知道計數(shù)器是在2011年1月1日的0時0分0秒置0的,那么就可以根據(jù)計數(shù)器的這個相對時間數(shù)值,計算得這個X時刻是2011年1月3日的0時0分0秒了。而計數(shù)器則會在(2011+136)年左右溢出,也就是說到了(2011+136)年時,如果我們還在使用這個計數(shù)器提供時間的話就會出現(xiàn)問題。在這個例子中,定時器被置0的這個時間被稱為計時元年,相對計時元年經(jīng)過的秒數(shù)稱為時間戳,也就是計數(shù)器中的值。
大多數(shù)操作系統(tǒng)都是利用時間戳和計時元年來計算當(dāng)前時間的,而這個時間戳和計時元年大家都取了同一個標(biāo)準(zhǔn)——UNIX時間戳和UNIX計時元年。UNIX計時元年被設(shè)置為格林威治時間1970年1月1日0時0分0秒,大概是為了紀(jì)念UNIX的誕生的時代吧,而UNIX時間戳即為當(dāng)前時間相對于UNIX計時元年經(jīng)過的秒數(shù)。因為UNIX時間戳主要用來表示當(dāng)前時間或者和電腦有關(guān)的日志時間(如文件創(chuàng)立時間,log發(fā)生時間等),考慮到所有電腦文件不可能在1970年前創(chuàng)立,所以用UNIX時間戳很少用來表示1970前的時間。
在這個計時系統(tǒng)中,使用的是有符號的32位整型變量來保存UNIX時間戳的,即實際可用計數(shù)位數(shù)比我們上面例子中的少了一位,少了這一位,UNIX 計時元年也相對提前了一半,這個計時方法在2038年1月19日03時14分07秒將會發(fā)生溢出,這個時間離我們并不遠(yuǎn),在設(shè)計預(yù)期壽命較長的設(shè)備需要注意。
小結(jié)
本章內(nèi)容介紹了CKS32F107系列RTC實時時鐘外設(shè)的硬件結(jié)構(gòu)和工作原理,并結(jié)合相關(guān)寄存器講解了與RTC控制相關(guān)的外設(shè)庫函數(shù)使用方法,最后介紹了UNIX時間戳的概念。從上述內(nèi)容可知,RTC外設(shè)是個連續(xù)計數(shù)的計數(shù)器,利用它提供的時間戳,可通過程序轉(zhuǎn)換輸出實時時鐘和日歷的功能,修改計數(shù)器的值則可以重新設(shè)置系統(tǒng)當(dāng)前的時間和日期。由于它的時鐘配置系統(tǒng)(RCC_BDCR寄存器)是在備份域,在系統(tǒng)復(fù)位或從待機(jī)模式喚醒后RTC的設(shè)置維持不變,而且使用備份域電源可以讓RTC計時器在主電源關(guān)掉的情況下仍然運(yùn)行,保證時間的正確。有了這些基礎(chǔ),下一節(jié)將詳細(xì)介紹如何利用RTC的計時功能實現(xiàn)一個簡單的萬年歷效果。
-
寄存器
+關(guān)注
關(guān)注
31文章
5433瀏覽量
124419 -
實時時鐘
+關(guān)注
關(guān)注
4文章
314瀏覽量
67057 -
定時器
+關(guān)注
關(guān)注
23文章
3298瀏覽量
118859 -
RTC
+關(guān)注
關(guān)注
2文章
622瀏覽量
68844
原文標(biāo)題:MCU微課堂|CKS32F107xx RTC(一)
文章出處:【微信號:中科芯MCU,微信公眾號:中科芯MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
STM32 RTC實時時鐘(一)

RTC是什么?RTC實時時鐘實驗
F2產(chǎn)品技術(shù)培訓(xùn)_11.實時時鐘(RTC)
一文看懂rtc實時時鐘和單片機(jī)時鐘的區(qū)別
淺談RTC實時時鐘特征與原理
stm32f4 RTC實時時鐘解析

STM32CubeMX系列|RTC實時時鐘

RTC實時時鐘的基本概念和工作原理
CKS32F107xx系列時鐘系統(tǒng)具體配置方法講解

評論