pzsb的笔记 https://bbs.21ic.com/?551778 [收藏] [复制] [RSS] 新手上路  大家多多指教!

日志

寻找最佳定时值 实现精确时钟

已有 964 次阅读2009-4-6 08:54 |个人分类:中断 定时|系统分类:单片机| 电子表, 精确定时

/*
多功能电子表设计 寻找最佳定时值 实现精确时钟


如果MCU晶振为12M,则一个机器周期为1us, 很容易计算时钟误差。
但现在晶振选了11.0592M, 这个值与串行通信密切相关——用波特率计算软件计算常用波特率就知道这是怎么回事了。
所以,对于一个没有用串行通信 又 需要精确定时的电子表来说,选11.0592M是不合适的。
如果硬是选了它,怎么办?
寻找最佳定时值,使时钟误差最小!
怎么找?
最省事的方法是不找,随便先一个,并在某个时刻校准:如让时钟运行一小时,与标准时间的差即为误差。每小时校准一次。
确实是个好办法,呵。
学习就是把简单的问题复杂化,把复杂的问题简单化。所以,我不走此路。
让我们来面对时钟误差这个问题: 你的时钟误差是多少?


晶振fosc
T0方式2,自动装定时初值。中断周期NT不要太小,太小了没等中断返回又进入了,系统没法工作!


机器周期 T=12/fosc
T0中断周期 NT=12N/fosc
设T0中断计数 SNT次时为1s
SNT=1/NT=fosc/(12N)
误差:SNT小数部分/SNT整数部分*100%  (SNT整数部分? 计算用浮点型,MCU实际使用的是整数)



  数据类型和范围:
  T0方式2,所以N为8位,范围0~255
  SNT类型uint,16位,范围 0~65535


  依SNT=fosc/(12N)设计如下程序,求最佳N,使时钟误差最小


  用求得的结果(N=120,SNT=7680)编程时钟模块
 实验结果:
 1分钟误差4s !? 呵呵,T0中断优先级没设置,总是被用于SEG显示的T1中断影响。
 设置T0优先级1,T1优先级0, 运行4小时肉眼没有发现时钟误差。
 继续实验中。 明天测量跑表精度,不过现在迫不及待地先发布这个程序~~~~~~~~~


  PZ
  2009年4月6日
*/


#include <iostream>
using namespace std;


double fosc=11059200;  // 11.0592MHz


void main()
{
 int n, i;
 double aSnt[257];
 double err;
 
 fosc/=12;


 for(n=256; n>100; n--) // 中断周期不能太小,取大概100us
 {
  aSnt[n]=fosc/n;
  if(aSnt[n]>65535)break;
 }


 cout<<endl<<"搜索数组,找最佳N,并输出时钟误差"<<endl;
 n++;
 err=1;
 double t;
 while(n<=256)
 {
  if((int)aSnt[n]==0)
   system("pause");
  t=aSnt[n]-(int)aSnt[n];
  t/=(int)aSnt[n];
  //cout<<aSnt[n]<<endl;
  if(err>t)
  {
   err=t;
   i=n;
  }
  n++;
 }
 
 cout<<"最佳N:"<<i<<endl;
 cout<<"此时SNT:"<<scientific<<aSnt<<endl;//
 cout<<"误差:"<<err<<endl;


 cout<<endl<<"// TH0=TL0="<<256-i<<endl;


 /////////////////////////////以下计算跑表的CNT/////////////////////////////////////
 // 跑表计时模为1hour,精度优先级低于时钟。根据时钟最高精度要求求得TH0(TL0)、SNT后,求跑表的CNT(C表示centi-second)
 cout<<endl<<endl<<"跑表CNT:"<<int(aSnt/100+0.5)<<endl;
}


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (2 个评论)

夏宁 2009-5-6 02:01
呵呵,好牛啊! 谢谢啦!
夏宁 2009-5-6 02:08
呵呵,好牛啊! 谢谢啦!