但是還有一些疑問:
(1)這個(gè)例子的readme.txt中并沒有說明要用MicroLIB這個(gè)庫的事情。
(2)如果不用硬件,而是用軟件仿真,也是不需要使用MicroLIB庫的。
因此,有關(guān)MicroLIB的問題還不是特別明確,還需要進(jìn)一步研究。是否是這段程序還用到了scanf的原因?
例子的運(yùn)行
如果是第一次運(yùn)行,那么會(huì)出現(xiàn)如下畫面:
即其中有提示RTC沒有初始化,要求進(jìn)行設(shè)置的提示,根據(jù)提示分別送入小時(shí),分鐘,秒的數(shù)值,即完成設(shè)置工作,程序不斷地將當(dāng)前時(shí)間通過串口送出。
如果在VBAT端接入后備電池,那么斷電后再上電顯示的信息如下:
其中提示RTC已初始化,不需要再進(jìn)行初始化,直接將時(shí)間不斷地從串口送出。
程序解讀
/**
* @brief Configures the RTC.
* @param None
* @retval None
*/
void RTC_Configuration(void)
{
/* 開啟PWR和BKP模塊的時(shí)鐘 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* 允許對(duì)BKP進(jìn)行存取操作*/
PWR_BackupAccessCmd(ENABLE);
/* 初始化BKP區(qū)域*/
BKP_DeInit();
/* LSE允許,這里L(fēng)SE是指外部接的32768HZ 晶振的一個(gè)振蕩器,它使用PC14和PC15兩條引腳。有關(guān)這部分的一些細(xì)節(jié)描述如下:
當(dāng)備份區(qū)域由V DD (內(nèi)部模擬開關(guān)連到V DD )供電時(shí),下述功能可用:
● PC14和PC15可以用于GPIO或LSE引腳
● PC13可以作為通用I/O口、TAMPER引腳、RTC校準(zhǔn)時(shí)鐘、RTC鬧鐘或秒輸出
當(dāng)后備區(qū)域由VBAT供電時(shí)(VDD消失后模擬開關(guān)連到VBAT),可以使用下述功能:
● PC14和PC15只能用于LSE引腳
● PC13可以作為TAMPER引腳、RTC鬧鐘或秒輸出
*/
RCC_LSEConfig(RCC_LSE_ON);
/* 等待LSE振蕩器就緒 */
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{}
/* 選擇LSE作為RTC的時(shí)鐘源
說明:RTC時(shí)鐘源可以是以下三種之一:
─ HSE 時(shí)鐘除以 128
─ LSE 振蕩器時(shí)鐘
─ LSI振蕩器時(shí)鐘
其中LSI是一個(gè)內(nèi)部的低頻RC振蕩器。關(guān)于RTC的這三個(gè)時(shí)鐘各有何特點(diǎn),見下面的說明。
*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/* RTC時(shí)鐘允許*/
RCC_RTCCLKCmd(ENABLE);
/* 等待RTC寄存器同步
理由如下:
15.3.3 讀 RTC 寄存器
RTC核完全獨(dú)立于RTC APB1接口。
軟件通過APB1接口訪問RTC的預(yù)分頻值、計(jì)數(shù)器值和鬧鐘值。但是,相關(guān)的可讀寄存器只在與RTC APB1時(shí)鐘進(jìn)行重新同步的RTC時(shí)鐘的上升沿被更新。RTC標(biāo)志也是如此的。
這意味著,如果APB1接口剛剛被開啟之后,在第一次的內(nèi)部寄存器更新之前,從APB1上讀出RTC寄存器的第一個(gè)值可能被破壞了(通常讀到0)。下述幾種情況下能夠發(fā)生這種情形:
● 發(fā)生系統(tǒng)復(fù)位或電源復(fù)位
● 系統(tǒng)剛從待機(jī)模式喚醒(參見4.3節(jié))。
● 系統(tǒng)剛從停機(jī)模式喚醒(參見4.3節(jié))。
所有以上情況中,APB1接口被禁止時(shí)(復(fù)位、無時(shí)鐘或斷電)RTC核仍保持運(yùn)行狀態(tài)。 因此,若在讀取RTC寄存器曾經(jīng)被禁止的RTC APB1接口,軟件首先須等待RTC_CRL寄存器中
的RSF位(寄存器同步標(biāo)志)被硬件置1。
{
/* Clear RSF flag */
RTC-》CRL &= (uint16_t)~RTC_FLAG_RSF;
/* Loop until RSF flag is set */
while ((RTC-》CRL & RTC_FLAG_RSF) == (uint16_t)RESET)
{
}
}
*/
RTC_WaitForSynchro();
/* 等待最后寫操作完成*/
RTC_WaitForLastTask();
/* 允許秒中斷,相應(yīng)代碼如下:
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RTC_IT(RTC_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RTC-》CRH |= RTC_IT;
}
else
{
RTC-》CRH &= (uint16_t)~RTC_IT;
}
}
而調(diào)用這段程序的代碼中的第一個(gè)參數(shù)是:
#define RTC_IT_SEC ((uint16_t)0x0001) /*!《 Second interrupt */
可見它是對(duì)RTC-》CRH的最低位進(jìn)行操作,CRH相關(guān)內(nèi)容見下面的圖。
*/
RTC_ITConfig(RTC_IT_SEC, ENABLE);
/* 等待最后的寫操作完成*/
RTC_WaitForLastTask();
/* 設(shè)置RTC預(yù)分頻器: set RTC period to 1sec */
RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
/* 等待最后的寫操作完成*/
RTC_WaitForLastTask();
}
下面的圖是有關(guān)RTC時(shí)鐘選擇的問題,其中說明了各種時(shí)鐘的工作特性:
下面的圖是有關(guān)RTC_CRH寄存器的描述,放在這里是為了說明SECIE標(biāo)志位。
評(píng)論