親測實驗,RTC使用內部低速時鐘LSI時,對RTC的配置過程

下面是一開始寫程序時,配置過程:

char RTCInit()
{

char count = 0;

StartTime.year = 16;
StartTime.month = 3;
StartTime.day = 5;
StartTime.hour = 20;
StartTime.min = 41;
StartTime.sec = 0;
 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR , ENABLE);

PWR_BackupAccessCmd(ENABLE);//打開後備域電源,可以訪問後備域寄存器



//(由於RTC的配置數據在後備域BKP中,所以只要Vbat或者VDD不丟電就不丟失(即使復位了也不丟失),故可通過讀BKP某個值來判斷是否丟電,進而判斷RTC是否需要初始化配置)
if(BKP_ReadBackupRegister(BKP_DR1) != 0xAA00)//Vbat且VDD掉電
{
BKP_DeInit(); //復位備份區域,將BKP寄存器清空


/////////////////////(時鐘配置部分)////////////////////////////

//RCC_LSEConfig(RCC_LSE_ON);//開啓外部低速晶振 LSE
RCC_LSICmd(ENABLE);//開啓內部低速晶振LSI

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && count<11) 
//while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == 0 && count<11)  //等待LSE啓振,判斷在2S內配置是否成功,不成功返回0
{
count++;
delay_ms(200);
}

if(count == 10)
{
return 0;//LSI啓振失敗
}

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
//RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//使用外部低速晶振LSE爲RTC時鐘源

RCC_RTCCLKCmd(ENABLE);//選擇使能RTC時鐘


RTC_WaitForLastTask();//等待上一次寫RTC任務完成(常用,只要涉及對RTC裏值的修改,都需要在修改後加上此函數)
RTC_WaitForSynchro();//等待與APB1的同步,才能讀RTC寄存器


///////////////// ////(寄存器配置部分)////////////////////////////

RTC_EnterConfigMode();//允許RTC配置
RTC_WaitForLastTask();//等待上一次寫RTC任務完成


RTC_SetPrescaler(40000);//分頻後爲1HZ
//RTC_SetPrescaler(32767);//分頻後爲1HZ
RTC_WaitForLastTask();//等待上一次寫RTC任務完成

   // RTC_ClearITPendingBit(RTC_IT_ALR);
   // RTC_WaitForLastTask();

RTC_ITConfig(RTC_IT_ALR , DISABLE);//使能鬧鐘中斷.  秒中斷RTC_IT_SEC

RTC_WaitForLastTask();//等待上一次寫RTC任務完成


SetWriteTime(&StartTime);//寫入起始日曆轉變給RTC


RTC_WaitForLastTask();//等待上一次寫RTC任務完成

RTC_ExitConfigMode(); //退出RTC配置模式


BKP_WriteBackupRegister(BKP_DR1, 0xAA00);//寫入想要的丟電判斷數據
GPIOInit(GPIOA ,GPIO_Pin_2, GPIO_Mode_Out_PP);//  LED   PA2

}

else//已經初始化過一次且沒掉電
{

RTC_WaitForSynchro();//等待與APB1的同步,才能讀RTC寄存器
RTC_EnterConfigMode();//允許RTC配置

RTC_ITConfig(RTC_IT_ALR, DISABLE); //使能鬧鐘中斷.  秒中斷RTC_IT_SEC

RTC_WaitForLastTask();//等待上一次寫RTC任務完成

RTC_ExitConfigMode(); //退出RTC配置模式
RTC_WaitForLastTask();//等待上一次寫RTC任務完成

GPIOInit(GPIOA ,GPIO_Pin_6, GPIO_Mode_Out_PP);//  LED   PA6
}


return 1;//配置成功
}


實驗結果,單片機剛上電PA2的LED燈可以亮,但按下復位時,PA6的LED燈不工作,按正常來說RTC在不掉電情況只要配置一次即可,按復位後應該進入else語句,進而點亮PA6的LED,但實際不然。通過在線調試,發現程序死在了RTC_WaitForSynchro();的同步函數裏。

通過各種調試,程序還是卡死,因此懷疑是不是使用內部低速時鐘LSI不穩定引起?(具體原因還不是很清楚??),不過當我把RTC的時鐘配置部分複製到else語句裏,奇蹟出現了,復位後PA6的LED可以點亮。因此不管是上電還是復位,都需要對RST的時鐘重新配置。於是有了下面正確的配置函數:


char RTCInit()

{

char count = 0;


StartTime.year = 16;
StartTime.month = 3;
StartTime.day = 5;
StartTime.hour = 20;
StartTime.min = 41;
StartTime.sec = 0;
 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR , ENABLE);

PWR_BackupAccessCmd(ENABLE);//打開後備域電源,可以訪問後備域寄存器

//(由於RTC的配置數據在後備域BKP中,所以只要Vbat或者VDD不丟電就不丟失(即使復位了也不丟失),故可通過讀BKP某個值來判斷是否丟電,進而判斷RTC是否需要初始化配置)
if(BKP_ReadBackupRegister(BKP_DR1) != 0xAA00)//Vbat且VDD掉電
{

BKP_DeInit(); //復位備份區域,將BKP寄存器清空

/////////////////////(時鐘配置部分)////////////////////////////

RCC_LSICmd(ENABLE);//開啓內部低速晶振LSI

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && count<11) //等待LSI啓振,判斷在2S內配置是否成功,不成功返回0
{
count++;
delay_ms(200);
}

if(count == 10)
{
return 0;//LSI啓振失敗
}

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

RCC_RTCCLKCmd(ENABLE);//選擇使能RTC時鐘


RTC_WaitForLastTask();//等待上一次寫RTC任務完成(常用,只要涉及對RTC裏值的修改,都需要在修改後加上此函數)
RTC_WaitForSynchro();//等待與APB1的同步,才能讀RTC寄存器


///////////////// ////(寄存器配置部分)////////////////////////////

RTC_EnterConfigMode();//允許RTC配置
RTC_WaitForLastTask();//等待上一次寫RTC任務完成


RTC_SetPrescaler(40000);//分頻後爲1HZ
//RTC_SetPrescaler(32767);//分頻後爲1HZ
RTC_WaitForLastTask();//等待上一次寫RTC任務完成


RTC_ITConfig(RTC_IT_ALR , DISABLE);//使能鬧鐘中斷.  秒中斷RTC_IT_SEC

RTC_WaitForLastTask();//等待上一次寫RTC任務完成


SetWriteTime(&StartTime);//寫入起始日曆轉變給RTC


RTC_WaitForLastTask();//等待上一次寫RTC任務完成

RTC_ExitConfigMode(); //退出RTC配置模式


BKP_WriteBackupRegister(BKP_DR1, 0xAA00);//寫入想要的丟電判斷數據
GPIOInit(GPIOA ,GPIO_Pin_2, GPIO_Mode_Out_PP);//  LED   PA2

}

else//已經初始化過一次且沒掉電
{
/////////////////////(時鐘配置部分)////////////////////////////
RCC_LSICmd(ENABLE);//開啓內部低速晶振LSI

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && count<11) 
{
count++;
delay_ms(200);
}

if(count == 10)
{
return 0;//LSI啓振失敗
}

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

RCC_RTCCLKCmd(ENABLE);//選擇使能RTC時鐘


RTC_WaitForLastTask();//等待上一次寫RTC任務完成(常用,只要涉及對RTC裏值的修改,都需要在修改後加上此函數)
RTC_WaitForSynchro();//等待與APB1的同步,才能讀RTC寄存器

///////////////// ////(寄存器配置部分)////////////////////////////

RTC_EnterConfigMode();//允許RTC配置

RTC_ITConfig(RTC_IT_ALR, DISABLE); //使能鬧鐘中斷.  秒中斷RTC_IT_SEC

RTC_WaitForLastTask();//等待上一次寫RTC任務完成

RTC_ExitConfigMode(); //退出RTC配置模式
RTC_WaitForLastTask();//等待上一次寫RTC任務完成

GPIOInit(GPIOA ,GPIO_Pin_6, GPIO_Mode_Out_PP);//  LED   PA6
}


return 1;//配置成功
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章