21,595
社区成员
发帖
与我相关
我的任务
分享
估计楼主有成本考虑,想以软补硬。 我觉得还是选个精度很高的外部时钟芯片比较好。。而且RTC不准,应该是32768不行。
片内晶振的精度可能还不及外部晶振。因为片外晶振是经过修值和针对频率精度筛选的。 你用它作基准的依据是什么?你测试过片间的离散度吗? 这就好比你有两种钟表。第一种精度比较一致,但有小的误差;第二种每一个精度都不同,误差范围更大。你会用第二种的时间其校对第一种吗? 我的意思,如果你没有可用基准,就直接读取 RTC 的值,当达到与你上次修正相距 48 分钟时,就重新设置为减小 0.1 秒的值。当然,如果是慢的话,就要加了。同理,如果 24 小时误差不是 3 秒,你就要重新计算修正间隔。 这个间隔就是你的 RTC 误差达到 0.1 秒的时间(标记误差为 e): t = 0.1/e * 24 * 60。 明白了吗?
你自己先想想,校准的基准是什么。 如果是已经成形的可以连接网络的应用,可以在主控层获取实时日期时间对 RTC 重新设置。 如果不是,那还是一楼的方法靠谱,换精度更高的晶振。 如果你的误差是固定的(比如每24小时快3秒),还有一个方法,主控层监控 RTC 的时间,每48分钟将 RTC 值减去 0.1 秒。这样,你的误差就保持在最大 0.1 秒的水平。
u8 My_RTC_Init(void)
{
RTC_InitTypeDef RTC_InitStructure;
u16 retry=0X1FFF;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);
if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0x5050)
{
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
retry++;
delay_ms(10);
}
if(retry==0)return 1;
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
RTC_InitStructure.RTC_SynchPrediv = 0xFF;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
// RTC_Set_Time(16,40,00,RTC_H12_PM);
// RTC_Set_Date(17,10,17,2);
RTC_WriteBackupRegister(RTC_BKP_DR0,0x5050);
}
return;
}
int main(void)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
u8 tbuf[40];
u8 t=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
uart_init(115200);
usmart_dev.init(84);
LED_Init();
My_RTC_Init();
RTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits,0);
RTC_CalibOutputConfig(RTC_CalibOutput_1Hz);
RTC_CalibOutputCmd(ENABLE);
while(1)
{
t++;
if((t%100)==0) //ÿ100ms¸üÐÂÒ»´ÎÏÔʾÊý¾Ý
{
RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
printf("Time:%02d:%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes,RTC_TimeStruct.RTC_Seconds);
RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
printf("Date:20%02d-%02d-%02d\r\n",RTC_DateStruct.RTC_Year,RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date);
printf("Week:%d\r\n",RTC_DateStruct.RTC_WeekDay);
}
if((t%20)==0)LED0=!LED0;
delay_ms(10);
}
}