Pro test experiment, when RTC uses internal low-speed clock LSI, the configuration process of RTC

The following is the configuration process when writing the program at the beginning:

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);//Turn on the backup domain power, you can access the backup domain register



//(Because the RTC configuration data is in the backup domain BKP, it will not be lost as long as Vbat or VDD is not lost (even if it is reset), so you can read a value of BKP to determine whether the power is lost, and then determine Does RTC need to initialize configuration)
if(BKP_ReadBackupRegister(BKP_DR1) != 0xAA00)//Vbat and VDD power down
{
BKP_DeInit(); //Reset the backup area and clear the BKP register


/ (Clock configuration part)

//RCC_LSEConfig(RCC_LSE_ON);//Turn on the external low-speed crystal oscillator LSE
RCC_LSICmd(ENABLE);//Turn on the internal low-speed crystal oscillator LSI

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && count<11) 
//while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == 0 && count<11) //Wait for the LSE to start and determine whether the configuration is successful within 2S, and return 0 if it is unsuccessful
{
count++;
delay_ms(200);
}

if(count == 10)
{
return 0;//LSI failed to start oscillation
}

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
//RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//Use the external low-speed crystal oscillator LSE as the RTC clock source

RCC_RTCCLKCmd(ENABLE);//Select to enable RTC clock


RTC_WaitForLastTask();//Wait for the completion of the last write RTC task (usually, as long as it involves the modification of the value in the RTC, this function needs to be added after the modification)
RTC_WaitForSynchro();//Wait for synchronization with APB1 before reading the RTC register


/ (Register configuration part)

RTC_EnterConfigMode();//Allow RTC configuration
RTC_WaitForLastTask();//Wait for the completion of the last write RTC task


RTC_SetPrescaler(40000); //1HZ after frequency division
//RTC_SetPrescaler(32767);//1HZ after frequency division
RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

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

RTC_ITConfig(RTC_IT_ALR, DISABLE);//Enable alarm interrupt. Second interrupt RTC_IT_SEC

RTC_WaitForLastTask();//Wait for the completion of the last write RTC task


SetWriteTime(&StartTime);//Write the start calendar to RTC


RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

RTC_ExitConfigMode(); //Exit RTC configuration mode


BKP_WriteBackupRegister(BKP_DR1, 0xAA00);//Write the desired power loss judgment data
GPIOInit(GPIOA ,GPIO_Pin_2, GPIO_Mode_Out_PP);//  LED   PA2

}

else//Has been initialized once and not powered down
{

RTC_WaitForSynchro();//Wait for synchronization with APB1 before reading the RTC register
RTC_EnterConfigMode();//Allow RTC configuration

RTC_ITConfig(RTC_IT_ALR, DISABLE); //Enable alarm interrupt. Second interrupt RTC_IT_SEC

RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

RTC_ExitConfigMode(); //Exit RTC configuration mode
RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

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


return 1;//Configuration is successful
}


The result of the experiment shows that the LED light of PA2 can be on when the MCU is powered on, but when reset is pressed, the LED light of PA6 does not work. Normally, the RTC only needs to be configured once without power failure. After pressing reset, it should enter the else statement. , And then light up the PA6 LED, but it is not. Through online debugging, it was found that the program died in the synchronization function of RTC_WaitForSynchro();.

Through various debugging, the program is still stuck, so I suspect that it is caused by the instability of the internal low-speed clock LSI? (The specific reason is not clear yet?), but when I copy the clock configuration part of RTC into the else statement, a miracle happened. After reset, the LED of PA6 can be lit. Therefore, regardless of power-on or reset, the RST clock needs to be reconfigured. So there is the following correct configuration function:


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);//Turn on the backup domain power, you can access the backup domain register

//(Because the RTC configuration data is in the backup domain BKP, it will not be lost as long as Vbat or VDD is not lost (even if it is reset), so you can read a value of BKP to determine whether the power is lost, and then determine Does RTC need to initialize configuration)
if(BKP_ReadBackupRegister(BKP_DR1) != 0xAA00)//Vbat and VDD power down
{

BKP_DeInit(); //Reset the backup area and clear the BKP register

/ (Clock configuration part)

RCC_LSICmd(ENABLE);//Turn on the internal low-speed crystal oscillator LSI

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && count<11) //Wait for the LSI to start and determine whether the configuration is successful within 2S, and return 0 if it is unsuccessful
{
count++;
delay_ms(200);
}

if(count == 10)
{
return 0;//LSI failed to start oscillation
}

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

RCC_RTCCLKCmd(ENABLE);//Select to enable RTC clock


RTC_WaitForLastTask();//Wait for the completion of the last write RTC task (usually, as long as it involves the modification of the value in the RTC, this function needs to be added after the modification)
RTC_WaitForSynchro();//Wait for synchronization with APB1 before reading the RTC register


/ (Register configuration part)

RTC_EnterConfigMode();//Allow RTC configuration
RTC_WaitForLastTask();//Wait for the completion of the last write RTC task


RTC_SetPrescaler(40000); //1HZ after frequency division
//RTC_SetPrescaler(32767);//1HZ after frequency division
RTC_WaitForLastTask();//Wait for the completion of the last write RTC task


RTC_ITConfig(RTC_IT_ALR, DISABLE);//Enable alarm interrupt. Second interrupt RTC_IT_SEC

RTC_WaitForLastTask();//Wait for the completion of the last write RTC task


SetWriteTime(&StartTime);//Write the start calendar to RTC


RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

RTC_ExitConfigMode(); //Exit RTC configuration mode


BKP_WriteBackupRegister(BKP_DR1, 0xAA00);//Write the desired power loss judgment data
GPIOInit(GPIOA ,GPIO_Pin_2, GPIO_Mode_Out_PP);//  LED   PA2

}

else//Has been initialized once and not powered down
{
/ (Clock configuration part)
RCC_LSICmd(ENABLE);//Turn on the internal low-speed crystal oscillator LSI

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

if(count == 10)
{
return 0;//LSI failed to start oscillation
}

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

RCC_RTCCLKCmd(ENABLE);//Select to enable RTC clock


RTC_WaitForLastTask();//Wait for the completion of the last write RTC task (usually, as long as it involves the modification of the value in the RTC, this function needs to be added after the modification)
RTC_WaitForSynchro();//Wait for synchronization with APB1 before reading the RTC register

/ (Register configuration part)

RTC_EnterConfigMode();//Allow RTC configuration

RTC_ITConfig(RTC_IT_ALR, DISABLE); //Enable alarm interrupt. Second interrupt RTC_IT_SEC

RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

RTC_ExitConfigMode(); //Exit RTC configuration mode
RTC_WaitForLastTask();//Wait for the completion of the last write RTC task

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


return 1;//Configuration is successful
}

Guess you like

Origin blog.csdn.net/ludaoyi88/article/details/50822348