亲测实验,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;//配置成功
}
  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值