如何对STM32F4的RTC进行自动校准

那笑已成往昔 2017-10-18 03:19:18
采用32768hz的外部晶振,RTC实时时钟,每天会产生3s的误差。如何进行自动校准,求各位大神指导
...全文
2575 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
of123 2017-10-25
  • 打赏
  • 举报
回复
引用 13 楼 tianxj001 的回复:
[quote=引用 12 楼 of123 的回复:] 哈哈,这个要看人家的具体应用需求和方案决策了。你的建议人家一开始就拒绝了的。 当然了,换个人设计,可能会完全不同。 我们总是要提供尽可能多的方案,说明优劣,供人家选择。我是做技术支持的,可能思路会有点不一样,不会坚持一种方案强加给用户。
果然,技术支持和我们开发的感觉真就是不一样,对开发而言,唯一的只有一个:性价比,别无二选,可用一元解决的,用1.2解决那就是错的。 [/quote]所以呀。他可能也是搞开发的,认准了他的唯一方案,而且他的标准也是唯一的,就是成本低。
of123 2017-10-23
  • 打赏
  • 举报
回复
引用 9 楼 fatalromeo 的回复:
我觉得还是选个精度很高的外部时钟芯片比较好。。而且RTC不准,应该是32768不行。
估计楼主有成本考虑,想以软补硬。
tianxj001 2017-10-23
  • 打赏
  • 举报
回复
引用 12 楼 of123 的回复:
哈哈,这个要看人家的具体应用需求和方案决策了。你的建议人家一开始就拒绝了的。 当然了,换个人设计,可能会完全不同。 我们总是要提供尽可能多的方案,说明优劣,供人家选择。我是做技术支持的,可能思路会有点不一样,不会坚持一种方案强加给用户。
果然,技术支持和我们开发的感觉真就是不一样,对开发而言,唯一的只有一个:性价比,别无二选,可用一元解决的,用1.2解决那就是错的。
hello_mcu 2017-10-23
  • 打赏
  • 举报
回复
我觉得还是选个精度很高的外部时钟芯片比较好。。而且RTC不准,应该是32768不行。
of123 2017-10-23
  • 打赏
  • 举报
回复
如果你是用中断方式处理的话,这个方案是可以的。 两种思路: 1 根据你芯片内置振荡器的离差,选择足以保证所有芯片在 48 分钟前但最接近于 48 分钟计满的计数值。在中断服务中,以轮询方式读 RTC 直至达到 48 秒。然后改写 RTC。此方法对 RTC 的校准较为一致,但主芯片开销略大。 2 按照你芯片内置振荡器的频率均值,设计一个标称时间 48 秒的计数器值。在中断服务中,立即读取和改写 RTC。优点是主芯片开销小,但 RTC 的补偿并不一致,只是得到了一个并不均等的但大大减小了的误差。 如果你用查询方式的话,就不如直接查询 RTC 了。
of123 2017-10-23
  • 打赏
  • 举报
回复
引用 11 楼 tianxj001 的回复:
引用 10 楼 of123 的回复:
[quote=引用 9 楼 fatalromeo 的回复:] 我觉得还是选个精度很高的外部时钟芯片比较好。。而且RTC不准,应该是32768不行。
估计楼主有成本考虑,想以软补硬。
这个以软补硬又有什么现实意义呢?内部振荡器绝对精度在短时间内,倒是可以校准到挺不错精度,但是RC振荡器长期精度只有10负4次精度,比便宜货石英晶体都低一个半数量级。每天差几秒,那32768晶体应该还在可以校准范围,用典型的可调小电容补偿一下应该就可以了。只需要调整OSC32_IN对地电容,就可以了。[/quote]哈哈,这个要看人家的具体应用需求和方案决策了。你的建议人家一开始就拒绝了的。 当然了,换个人设计,可能会完全不同。 我们总是要提供尽可能多的方案,说明优劣,供人家选择。我是做技术支持的,可能思路会有点不一样,不会坚持一种方案强加给用户。
tianxj001 2017-10-23
  • 打赏
  • 举报
回复
引用 10 楼 of123 的回复:
引用 9 楼 fatalromeo 的回复:
我觉得还是选个精度很高的外部时钟芯片比较好。。而且RTC不准,应该是32768不行。
估计楼主有成本考虑,想以软补硬。
这个以软补硬又有什么现实意义呢?内部振荡器绝对精度在短时间内,倒是可以校准到挺不错精度,但是RC振荡器长期精度只有10负4次精度,比便宜货石英晶体都低一个半数量级。每天差几秒,那32768晶体应该还在可以校准范围,用典型的可调小电容补偿一下应该就可以了。只需要调整OSC32_IN对地电容,就可以了。
那笑已成往昔 2017-10-21
  • 打赏
  • 举报
回复
引用 6 楼 of123 的回复:
片内晶振的精度可能还不及外部晶振。因为片外晶振是经过修值和针对频率精度筛选的。 你用它作基准的依据是什么?你测试过片间的离散度吗? 这就好比你有两种钟表。第一种精度比较一致,但有小的误差;第二种每一个精度都不同,误差范围更大。你会用第二种的时间其校对第一种吗? 我的意思,如果你没有可用基准,就直接读取 RTC 的值,当达到与你上次修正相距 48 分钟时,就重新设置为减小 0.1 秒的值。当然,如果是慢的话,就要加了。同理,如果 24 小时误差不是 3 秒,你就要重新计算修正间隔。 这个间隔就是你的 RTC 误差达到 0.1 秒的时间(标记误差为 e): t = 0.1/e * 24 * 60。 明白了吗?
我用定时做秒计数器,当计数值到达阈值时,先读取当前RTC时间啊,再对RTC的秒做减一处理可行吗?
of123 2017-10-20
  • 打赏
  • 举报
回复
片内晶振的精度可能还不及外部晶振。因为片外晶振是经过修值和针对频率精度筛选的。 你用它作基准的依据是什么?你测试过片间的离散度吗? 这就好比你有两种钟表。第一种精度比较一致,但有小的误差;第二种每一个精度都不同,误差范围更大。你会用第二种的时间其校对第一种吗? 我的意思,如果你没有可用基准,就直接读取 RTC 的值,当达到与你上次修正相距 48 分钟时,就重新设置为减小 0.1 秒的值。当然,如果是慢的话,就要加了。同理,如果 24 小时误差不是 3 秒,你就要重新计算修正间隔。 这个间隔就是你的 RTC 误差达到 0.1 秒的时间(标记误差为 e): t = 0.1/e * 24 * 60。 明白了吗?
of123 2017-10-19
  • 打赏
  • 举报
回复
你自己先想想,校准的基准是什么。 如果是已经成形的可以连接网络的应用,可以在主控层获取实时日期时间对 RTC 重新设置。 如果不是,那还是一楼的方法靠谱,换精度更高的晶振。 如果你的误差是固定的(比如每24小时快3秒),还有一个方法,主控层监控 RTC 的时间,每48分钟将 RTC 值减去 0.1 秒。这样,你的误差就保持在最大 0.1 秒的水平。
那笑已成往昔 2017-10-19
  • 打赏
  • 举报
回复
来个大神,指导下
tianxj001 2017-10-19
  • 打赏
  • 举报
回复 1
8MHz晶振和32768晶振是同一个级别的器件,用同一级别的时钟去校准另一个时钟,不知道这样做的现实意义在哪? 哪怕你手上正好8MHz晶振比较准,可以对比较不准的32768晶振进行校准,但是这是没有工程意义上的作用的。换一个机器,你可能越校准越差。普通型无源晶振10-5次方精度。都一样。
那笑已成往昔 2017-10-19
  • 打赏
  • 举报
回复
引用 3 楼 of123 的回复:
你自己先想想,校准的基准是什么。 如果是已经成形的可以连接网络的应用,可以在主控层获取实时日期时间对 RTC 重新设置。 如果不是,那还是一楼的方法靠谱,换精度更高的晶振。 如果你的误差是固定的(比如每24小时快3秒),还有一个方法,主控层监控 RTC 的时间,每48分钟将 RTC 值减去 0.1 秒。这样,你的误差就保持在最大 0.1 秒的水平。
基准是8M内部晶振。每48分钟将 RTC 值减去 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);
		}	

}
tianxj001 2017-10-18
  • 打赏
  • 举报
回复
目前,不需要人工干预的实时钟,首选GPS,备选CDMA,貌似再也找不到性价比更高的方案了。有了这2个模块,貌似单片机又不需要实时钟了,取模块时钟数字就可以了。 过去倒是弄过网络授时定时比对。可需要接入互联网,必须能解释NTP协议。这基本上就是一个小系统的能力了。 单独单片机自动校准时钟简单方案是不存在的,因为比对的必须是一个精确时钟系统,比如原子钟,淘宝上面倒是有拆机货原子钟卖,价格也完全可以接受。而当你有了精确时钟系统后,普通32768晶振又有什么用途呢? 所以,希望时钟精确的,从成本考虑,可以使用温补晶体,目前一般温补晶体可以做到±1PPM,基本上可以做到几个月不差一秒,当然,已知频率必须确信已经经过校准。

21,595

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧