實(shí)時(shí)時(shí)鐘(Real-Time Clock,RTC)常用于制作時(shí)鐘日歷。RTC電路分屬于兩個(gè)電源域:備份域和VDD電源域。RTC的核心計(jì)數(shù)部分在備份域中,可在VDD斷電VBAT供電時(shí)保持RTC的計(jì)數(shù),當(dāng)系統(tǒng)復(fù)位或者從待機(jī)模式喚醒時(shí),RTC的設(shè)置和時(shí)間也都保持不變。本期內(nèi)容將通過一個(gè)顯示當(dāng)前時(shí)間的例程帶領(lǐng)大家初步了解GD32VF103的RTC外設(shè)的使用方法。
系統(tǒng)環(huán)境:Windows 10-64bit
軟件平臺(tái):NucleiStudio IDE 202102版或 PlatformIO IDE
GD32VF103的RTC電路
GD32VF103的RTC電路包含兩個(gè)主要部分,分別是位于PCLK1時(shí)鐘域的APB接口和位于RTC時(shí)鐘域的RTC內(nèi)核:
APB接口與APB1總線相連,包含一組寄存器,可通過APB1總線對(duì)其進(jìn)行訪問。
RTC內(nèi)核包含兩個(gè)主要模塊,一個(gè)是RTC預(yù)分頻模塊,模塊包含一個(gè)20位可編程預(yù)分頻器,該分頻器可以通過對(duì)RTC時(shí)鐘源分頻產(chǎn)生SC_CLK,如果RTC_INTEN寄存器中的秒中斷標(biāo)志位被使能,在每個(gè)SC_CLK上升沿,RTC會(huì)產(chǎn)生一個(gè)秒中斷。另外一個(gè)模塊是一個(gè)32位可編程計(jì)數(shù)器,其數(shù)值可以被初始化為當(dāng)前系統(tǒng)時(shí)間。如果RTC_INTEN的鬧鐘中斷標(biāo)志位被使能,RTC會(huì)在系統(tǒng)時(shí)間等于鬧鐘時(shí)間(存儲(chǔ)于RTC_ALRMH/L寄存器)時(shí)產(chǎn)生一個(gè)鬧鐘中斷。
RTC的主要特征如下:
32位可編程計(jì)數(shù)器,用于計(jì)數(shù)運(yùn)行時(shí)間
可編程的預(yù)分頻器,分頻系數(shù)最高可達(dá)2^20
獨(dú)立時(shí)鐘域:
PCLK1時(shí)鐘域
RTC時(shí)鐘域(該時(shí)鐘域必須比PCLK1時(shí)鐘至少慢4倍)
RTC時(shí)鐘源:
HXTAL時(shí)鐘除以128
LXTAL振蕩電路時(shí)鐘
IRC40K振蕩電路時(shí)鐘
可屏蔽的中斷源:
鬧鐘中斷
秒中斷
溢出中斷
實(shí)驗(yàn)部分
本期的實(shí)驗(yàn)將使用RV-STAR的RTC外設(shè)實(shí)現(xiàn)顯示當(dāng)前時(shí)間的功能,例程的整體實(shí)現(xiàn)思路如下:
首先需要初始化RTC外設(shè):使能時(shí)鐘源和配置預(yù)分頻系數(shù)等,對(duì)于是否通過串口打印輸出當(dāng)前時(shí)間,聲明一個(gè)狀態(tài)變量并賦值為0;
然后用戶通過串口人工輸入當(dāng)前的時(shí)間對(duì)RTC的寄存器進(jìn)行配置,RTC進(jìn)入自動(dòng)計(jì)數(shù)模式,每秒產(chǎn)生一個(gè)中斷,在中斷服務(wù)程序中將狀態(tài)變量置1
主程序中運(yùn)行一個(gè)循環(huán)體,判斷狀態(tài)變量的值,如果為1,則讀取RTC寄存器存儲(chǔ)的當(dāng)前時(shí)間然后打印輸出到串口
重點(diǎn)講解一下RTC外設(shè)的初始化配置,其代碼片段如下:
void rtc_configuration(void)
{
/* enable PMU and BKPI clocks */
rcu_periph_clock_enable(RCU_BKPI);
rcu_periph_clock_enable(RCU_PMU);
/* allow access to BKP domain */
pmu_backup_write_enable();
/* reset backup domain */
bkp_deinit();
/* enable LXTAL */
rcu_osci_on(RCU_LXTAL);
/* wait till LXTAL is ready */
rcu_osci_stab_wait(RCU_LXTAL);
/* select RCU_LXTAL as RTC clock source */
rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
/* enable RTC Clock */
rcu_periph_clock_enable(RCU_RTC);
/* wait for RTC registers synchronization */
rtc_register_sync_wait();
/* wait until last write operation on RTC registers has finished */
rtc_lwoff_wait();
/* enable the RTC second interrupt*/
rtc_interrupt_enable(RTC_INT_SECOND);
/* wait until last write operation on RTC registers has finished */
rtc_lwoff_wait();
/* set RTC prescaler: set RTC period to 1s */
rtc_prescaler_set(32767);
/* wait until last write operation on RTC registers has finished */
rtc_lwoff_wait();
}
由于使用RV-STAR板載的32.768K的晶振作為RTC時(shí)鐘源,因此配置時(shí)要選擇LXTAL,同時(shí)要注意預(yù)分頻系數(shù)的設(shè)置,另外每次對(duì)RTC的寫操作,均要等待寫入完成,例程其余部分的代碼均有詳細(xì)注釋,讀者們可以自行閱讀,相關(guān)代碼請(qǐng)參考RVMCU網(wǎng)站專欄對(duì)應(yīng)鏈接。
將完整代碼進(jìn)行編譯上傳至RV-STAR開發(fā)板,打開串口終端(圖中使用PlatformIO的串口終端,也可以使用其他的串口工具):
然后在串口終端中依次輸入當(dāng)前時(shí)間的時(shí)、分、秒數(shù)據(jù),時(shí)鐘功能就正常開啟了,將會(huì)每秒刷新輸出一次當(dāng)前時(shí)間,如下圖:
如果按下復(fù)位按鈕,程序會(huì)重啟,但只要保持通電,RTC的計(jì)時(shí)會(huì)正常進(jìn)行,數(shù)據(jù)也不會(huì)丟失,按下復(fù)位后的串口打印結(jié)果見下圖:
復(fù)位后依然正常顯示當(dāng)前時(shí)間,說明RTC外設(shè)按照我們期望的功能在運(yùn)行。如果拔掉USB數(shù)據(jù)線,供電完全切斷,那數(shù)據(jù)將會(huì)丟失,需要再次配置當(dāng)前時(shí)間。
有條件的讀者也可以嘗試將鋰電池及底座焊接到RV-STAR背面預(yù)留的焊接處,那樣即使USB數(shù)據(jù)線的供電切斷,RTC也可以依靠電池電源保存數(shù)據(jù)并持續(xù)計(jì)時(shí)。
由于GD32VF103的RTC外設(shè)較為簡單,硬件上僅有時(shí)鐘(時(shí)/分/秒)相關(guān)的寄存器,而沒有日歷相關(guān)的寄存器,因此如果要實(shí)現(xiàn)完整的日歷時(shí)鐘顯示,需要用軟件來實(shí)現(xiàn)日歷,留給讀者自行探索。