|
|
楼主 |
发表于 2020-3-28 21:48:54
|
显示全部楼层
本帖最后由 TIGGER 于 2020-3-28 21:53 编辑
2、进一步对时钟进行校准
第一轮时钟精度很低,误差达到27MS/S,为了进一步提高精度,做了如下改进:
首先,采用中断的方式,产生时钟频率。即程序编写中采用T0定时器的方式2,即8位定时器,自动重装初值,以降低用软件反复设置初值,带来的误差。
定时器设置:TL0初值设为6,每250次,产生一次中断。在晶振频率12M下,为250us中断一次。程序中累计4000次为1S。烧录程序时,设定频率12.000MHz,实际烧录频率为12.011MHz。经校准,程序累计次数改为3999后,时钟精度达到:0.2ms/s(手动测量,精度有限),即每小时误差0.72s,一天误差17.28s。
另外,发现两处计算错误,一处为秒循环,一处为分钟循环。应该循环到59,清零,而不是60。
程序如下,如有更好的提高时钟精度的方法,希望加入讨论。
#include <intrins.h>
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sfr P2M0=0x96; //声明 P2引脚模式寄存器
sfr P3M0=0xb2; //声明 P3引脚模式寄存器
sbit a=P3^5;
sbit b=P2^1;
sbit c=P2^3;
sbit d=P3^3;
sbit e=P3^2;
sbit f=P3^6;
sbit g=P2^4;
sbit dp=P2^2;
sbit seg1=P3^4;
sbit seg2=P3^7;
sbit seg3=P2^0;
sbit seg4=P2^5;
sbit key1=P1^6;
sbit key2=P1^5;
uchar key1_action;
uchar key1_old;
uchar key2_action;
uchar key2_old;
unsigned int second;
void Delay1ms() //@12.000MHz
{
uchar i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void Delay_n_ms(uint n) //延时n毫秒函数
{
while(n)
{
Delay1ms();
n=n-1;//每循环一次n减小1
}
}
void display(unsigned char x)//控制数码管显示内容的函数
{
//判断x的值来决定显示什么
if(x==0){a=0;b=0;c=0;d=0;e=0;f=0;g=1; }//显示“0”
if(x==1){a=1;b=0;c=0;d=1;e=1;f=1;g=1;} //显示“1”
if(x==2){a=0;b=0;c=1;d=0;e=0;f=1;g=0;} //显示“2”
if(x==3){a=0;b=0;c=0;d=0;e=1;f=1;g=0;} //显示“3”
if(x==4){a=1;b=0;c=0;d=1;e=1;f=0;g=0;} //显示“4”
if(x==5){a=0;b=1;c=0;d=0;e=1;f=0;g=0;} //显示“5”
if(x==6){a=0;b=1;c=0;d=0;e=0;f=0;g=0;} //显示“6”
if(x==7){a=0;b=0;c=0;d=1;e=1;f=1;g=1;} //显示“7”
if(x==8){a=0;b=0;c=0;d=0;e=0;f=0;g=0;} //显示“8”
if(x==9){a=0;b=0;c=0;d=0;e=1;f=0;g=0;} //显示“9”
}
void main()
{
unsigned int h1,h2,m1,m2,minute,m,h;
P2M0=0x3F;
P3M0=0xF4;
h1=0;h2=0;m1=0;m2=0;m=0;h=9;
h1=h/10;
h2=h%10;
key1_old=0; //按键没按下去,是低电平
key2_old=0;
TMOD=0x02;//使用T0中断的模式2,自动装初值,减小时钟误差
TH0=6; //装初值,
TL0=6;
EA=1;
ET0=1;
TR0=1;
while(1)
{
if(h1==1)
{
seg1=1;seg2=0;seg3=0;seg4=0;
display(h1);
Delay_n_ms(1);
}
seg1=0;seg2=1;seg3=0;seg4=0;
display(h2);
Delay_n_ms(1);
seg1=0;seg2=0;seg3=1;seg4=0;
display(m1);
Delay_n_ms(1);
seg1=0;seg2=0;seg3=0;seg4=1;
display(m2);
Delay_n_ms(1);
if(key1==0)
{
if(key1_old==1)
{
key1_action=1;
m=m+1;
}
}
key1_old=key1;
m1=m/10;
m2=m%10;
if(key2==0)
{
if(key2_old==1)
{
key2_action=1;
h=h+1;
}
}
key2_old=key2;
h1=h/10;
h2=h%10;
if(h>12){h=1;}
if(second>3999) //中断一次250us,4000次,1秒(1、慢0.4814MS/S,增减少计数:481/250=1.9256,2、快0.2023MS/S,增加计数:202.3/250=0.8091,不到1 )
{
second=0;
dp=~dp;
minute=minute+1;
if(minute>59) //60次,1分钟
{
minute=0;
m=m+1;
m1=m/10;
m2=m%10;
if(m>59) //60次,1小时
{
m=0;
h=h+1;
h1=h/10;
h2=h%10;
if(h>12){h=1;}
}
}
}
}
}
void T0_time() interrupt 1
{
second=second+1;
}
|
| |