×
单片机 > 单片机程序设计 > 详情

关于STM32使用RTC时复位后程序死在 RTC

发布时间:2020-05-30 发布时间:
|

在软件仿真时如果不需要配置,则程序会死在 RTC_WaitForSynchro() 函数中。而下载到硬件上时,有时候可以跑,有时候也会在该函数中死循环。


可能的原因:

首先,一定要确认是否使能了对后备寄存器和RTC的访问。

系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问: 


● 设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
● 设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问
PWR_BackupAccessCmd(ENABLE);

另外还要使能RTC时钟 RCC_RTCCLKCmd(ENABLE); 虽然该函数的说明中说只在RCC_RTCCLKConfig()函数调用之后才能调用,但是实际上如果不调用该函数,仿真时就会在 RTC_WaitForSynchro() 函数中死循环,等待RTC时钟同步。

也就是说,不论是否需要配置RTC寄存器,每次系统复位都需要执行如下操作:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);RCC_RTCCLKCmd(ENABLE);

其次,STM32的RTC对外部LSE要求比较高,最好使用负载电容为6pF的晶振。在芯片的DataSheet中有明确的说明,不能使用12.5pF的晶振。“ To avoid exceeding the maximum value of CL1 and CL2 (15 pF) it is strongly recommended to use a resonator with a load capacitance CL≤ 7 pF. Never use a resonator with a load

capacitance of 12.5 pF.”


参考代码:
#include "RTC.h"
__IO uint32_t TimeDisplay;
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);        
NVIC_InitStructure.NVIC_IRQChannel=RTC_IRQn;           
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_Init(&NVIC_InitStructure);                       


}


void RTC_Config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR,ENABLE); 
PWR_BackupAccessCmd(ENABLE); 
BKP_DeInit(); 
RCC_LSEConfig(RCC_LSE_ON);  
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY)==RESET){} 
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); 
RCC_RTCCLKCmd(ENABLE); 
RTC_WaitForSynchro();      
RTC_WaitForLastTask();  
RTC_ITConfig(RTC_IT_SEC,ENABLE); 
RTC_WaitForLastTask(); 
RTC_SetPrescaler(32767); 
RTC_WaitForLastTask(); 
}


void Time_Ajust(void)
{
RTC_WaitForLastTask();
RTC_SetCounter(Time_Regulate());
RTC_WaitForLastTask();  
}


uint32_t Time_Regulate()
{
uint32_t temp_hour=0xff,temp_minute=0xff,temp_sec=0xff;

printf("Set hour:");
while(temp_hour==0xff){
USART_Scanf(23);
}
printf("  %d",temp_hour);
printf("Set minute:");
while(temp_minute==0xff){
USART_Scanf(59);
}
printf("  %d",temp_minute);
printf("Set second:");
while(temp_sec==0xff){
USART_Scanf(59);
}
printf("  %d",temp_sec);

return temp_hour*3600+temp_minute*60+temp_sec;
}




void RTC_Init(void)
{
if(BKP_ReadBackupRegister(BKP_DR1)==0xA5A5){

printf("\r\n This is a RTC demo! \r\n");
printf("\r\n RTC not yet configured \r\n");

RTC_Config();

Time_Ajust();

}
if(RCC_GetFlagStatus(RCC_FLAG_PORRST)!=RESET)
{
printf("\r\n not occured \r\n");
}
else if(RCC_GetFlagStatus(RCC_FLAG_PINRST)!=RESET)
{
printf("\r\n no need to config \r\n");
}
RTC_WaitForSynchro(); 
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();



}


void Time_show(void)
{
printf("\r\n");
while(1){
if(TimeDisplay==0)
{
Time_Display(RTC_GetCounter());
TimeDisplay=1;
}
}
}


void Time_Display(uint32_t Timewar)
{
unsigned int min=0,hour=0,sec=0;

hour=Timewar/3600;
min=Timewar%3600/60;
sec=Timewar%60;

printf("%.2d:%.2d:%.2d",hour,min,sec);

}


uint8_t USART_Scanf(uint32_t value)
{
uint32_t index=0;
uint32_t temp[2]={0,0};

while(index<2){
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)==RESET){}
temp[index]=USART_ReceiveData(USART1);
index++;
if(temp[index-1]



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计