数字钟误差原因分析及解决方案不考虑晶振等固件的误差,因而系统误差不可能来自于硬件,而应该主要来自于软件方面.系统每次调用定时中断程序的过程中,硬件并没有自动进入下一个定时周期,而是在调用中断程序以后由软件置数来实现的.而在程序调用过程中,堆栈建立、参数传递等都是需要耗时,而这些时间都被无形中加到了定时长度中去.所以,使得每次定时长度都大于理论推导值,在宏观上表现出来就是系统比理论计算出来的结果变慢了。另外,由于系统每次调用中断处理程序所执行的操作都是相同的,也就是说,系统每次定时的时间误差应该是一个常数,另外,在调时过程中因按键按下后的消抖延时以及等待按键释放这一时间段内会有误差。综上所述,系统的误差主要来自以下几个方面:一、人为误差(1)定时所引起的误差主要表现在对时上。由于自己写的对时程序只是对分和小时,而秒始终处于走时状态,这样写对时时很难做到和标准时间一致,造成误差。解决方案:对时时关闭计时中断;(2)按键所引起的误差解决方案:计算出防抖次数,然后再把防抖时的延时时间与防抖次数相乘,在加到总时间中去;此方法仅适用于按键用中断的方法扫描。二、单片机本身之误差1、数字钟要工作,要用到计数器,89C51单片机两个计数器有四种工作方式,工作方式1和工作方式2在进入中断程序时都要进行重装初值,重装初值需要消耗机器周期,从而带来了误差。解决方案:(1)重设单片机定时器的工作方式。通过设置TMOD寄存器中的M1M2位为10选择定时器方式2,方式2被称为8位初值自动重装的8位定时器/计数器,THX别称为常数缓冲器,当TLX计数溢出时,在溢出标志位TFX置1的同时,还自动地将THX中的常数重新装入TLX中,使TLX从初值开始重新计数,这样避免了人为软件重装初值所带来的误差,从而可以提高定时的精度。(2)用定时器计算出延时,然后加到总时间中去。定时计数器的初始值设置公式推导系统中所选用的晶振的频率为fosc,则机器周期为:公式1:t0=12/fosc.设定时器要求的中断频率为k,计数器位数为n,则定时计数器的初值X设置有如下公式:kXnt/1)(*20=-[2]。于是:原始公:021/(*)NXkt=-而实验测得的数据显示,这个公式所得的结果并不可靠:(下表中的所有数据都是在计数器初始值严格按照原始公式给出的条件下测得,以个人计算机机系统时钟为标准)。从表1中的数据可知,严格按照原始公式得出的计数初值是存在极大误差的,这个误差总使系统时间变慢,而且,系统时间的误差值随着每秒中断次数的增多而增大,随计时总长的增长而增大,并且总是成比例(在误差允许的范围内)。这就是说,系统的误差跟每秒中断次数和个人计算机标准时长的乘积(即中断总次数)成正比。也就是说,每次中断计时的时间误差是一个常数。误差来源分析不考虑晶振等固件的误差,则系统机器周期可以由公式1准确给出,因而系统误差不可能来自于硬件,而应该主要来自于软件方面。系统每次调用定时中断程序的过程中,硬件并没有自动进入下一个定时周期,而是在调用中断程序以后由软件置数来实现的。而在程序调用过程中,堆栈建立,参数传递等都是需要耗时的,而这些时间都被无形中加到了定时长度中去。所以,使得每次定时长度都大于理论推导值,在宏观上表现出来就是系统比理论计算出来的结果变慢了(这于表格1所得的结论恰好一致)。另外,由于系统每次调用中断处理程序所执行的操作都是相同的,也就是说,系统每次定时的时间误差应该是一个常数(这也恰好跟实验数据相吻合)。由上面的数据和分析可知,原始公式应该修改为:公式2:021/(*)NXktx=-+D则由表格1,关于的计算公式如下:公式3:0||/(60***)XtTktD=D由表格1数据,实际中要求k最小,而又不影响显示效果,才能使误差越小,故实测中取k=160。根据表格一计算得≈20(所用晶振频率为11.0592MHz)。按表1的实验方法,得表2:这些数据较表1已有很大准确性,但与实际应用还有一定差距。末两行是根据前面参数规律稍做改动得到的,与公式2有一定出入,但与个人计算机系统标准时间已经相当接近。由于表1的数据本身是肉眼估出来的,本身就带有很大的误差,实际运用可用精密仪器得到表1数据,则系统参数可以更进一步接近实用值。在KeiluVision3软件中验证定时器T0每50ms产生一次中断的时间。在初5始化中费时为551μs,每一次中断时间应该考虑该项的影响。在实际处理中可以利用两次中断时间的差来作为定时器的中断时间间隔。通过测试,得到第一次为0.05055642s,第二次为0.10056185s,第三次为0.15056728s。可以看出,每中断一次会比定时值长了5.43μs即5个机器周期,所以,应该在给定时器赋初值时加上这个误差,可以把中断服务程序作如下修改:TH0=(65536-50000)/256+5/256;TL0=(65536-50000)%256+5%256;2、中断优先级造成的误差如在中断中设置中断优先级即可,具体步骤为:在初始化程序时,把定时器0的中断优先级设为最高,IP=0xE2。在以后的运行中,不论遇到何种中断,都是按照IP中所设置的优先级来中断,进而减小了中断优先级带来的误差。