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