php计时器每过24小时结果加一倍,单片机时钟24小时慢了21.5秒 如何修改初值校正呢?...

如果不使用专用时钟芯片而是使用定时器做时基,单片机时钟的精准度取决于晶振的精准度和编程技巧。可以使日误差控制在1秒。给你一个示例参考,基于TX-1C实验板。

//K1键调整选择,K2键+,长按连+,K3键-,长按连-,K4键闹钟设置

//定时器初始化程序根据晶振频率选择

//主程序循环一次必须小于100us,否则要更改定时器周期

//用计数法代替软件延时,提高走时精度

//数码管采用分时动态显示,约2ms显示1位

#include

#define uint unsigned int

#define uchar unsigned char

#define key_S 300                                                //宏定义短按(约20ms)

#define key_L 6000                                        //宏定义长按(约2/3s)

#define key_M 3000                                        //宏定义长按(约1/3s)

sbit K1 = P3^4;                                                //调整选择/退出

sbit K2 = P3^5;                                                //++,长按连+

sbit K3 = P3^6;                                                //--,长按连-

sbit K4 = P3^7;                                                //调整时间

sbit dula=P2^6;                                                //段选

sbit wela=P2^7;                                                //位选

sbit Buzzer=P2^3;                                                //蜂鸣器

uchar code table[]={                                        //0~F数组

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

uint Cnt100us;                                                        //定义100微秒变量

uchar hour=12,min=0,sec=0;                        //定义时、分、秒变量

uchar hour4=0,min4=0;                                //定义闹钟时、分变量

uchar  Choice=0,Choice4=0;                        //调整时间、闹钟选择变量

bit Buzzer_sign;                                                //蜂鸣器闹钟标志

bit Twinkle,second=1;                                //闪烁标志、秒标志

/**************************************

定时器0初始化程序 100微秒@12.000MHz

**************************************/

/*

void Timer0Init()                                        //100微秒@12.000MHz

{

TMOD = 0x02;                                        //设置自动重载模式

TL0 = 0x9C;                                                //设置定时初值

TH0 = 0x9C;                                                //设置定时重载值

TF0 = 0;                                                //清除TF0标志

TR0 = 1;                                                //定时器0开始计时

}

*/

/***************************************

定时器0/1初始化程序 100微秒@11.0592MHz

***************************************/

void Timer_Init()                                        //100微秒@11.0592MHz

{

TMOD = 0x22;                                        //设置自动重载模式

TL0 = 0xA4;                                                //设置定时初值

TH0 = 0xA4;                                                //设置定时重载值

TL1 = 0x1A;                                        //设置定时初值250微秒@11.0592MHz

TH1 = 0x1A;                                        //设置定时重载值

TF0 = 0;                                                //清除TF0标志

TR0 = 1;                                                //定时器0开始计时

TF1 = 0;                                                //清除TF1标志

//        TR1 = 1;                                                //定时器1开始计时

EA=1;                                                        //开总中断

ET1=1;                                                //开定时器1中断

}

/*************************

按键扫描程序

*************************/

void key_scan()

{

static bit key1_sign,key4_sign;                        //按键自锁标志变量

static uint count1,count2,count3=0,count4=0;//消抖计数变量

if(!K1)                                                        //检测按键1按下

{

count1++;                                        //消抖计数1自+1

if((count1>=key_S)&&(key1_sign==0))//检测消抖计数与按键1自锁标志

{

key1_sign=1;                        //按键1自锁标志置1

Choice++;                                //调整选择变量自+1

if(Choice>=4)                        //调整时间选择0正常走时,1调时,2调分,3调秒

{

Choice=0;                        //调整时间选择清0

TF0=0;                                //定时器溢出标志TF0清0

Cnt100us=0;                        //时间变量Cnt100us自+1

}

}

}

else

{

key1_sign=0;                                //按键1自锁标志清0

count1=0;                                        //消抖计数count1清0

}

if(!K2)

{

count2++;

if(count2>=key_L)                        //长按快调

{

if(Choice==1)                        //选择变量1调时

{

hour++;

if(hour>=24)

hour=0;

}

if(Choice==2)                        //选择变量2调分

{

min++;

if(min>=60)

min=0;

}

if(Choice==3)                        //选择变量3调秒

{

sec++;

if(sec>=60)

sec=0;

}

if(Choice4==1)                        //选择变量1调时

{

hour4++;

if(hour4>=24)

hour4=0;

}

if(Choice4==2)                        //选择变量2调分

{

min4++;

if(min4>=60)

min4=0;

}

count2=key_M;

}

}

else                                                        //按键抬起

{

if(count2>key_S && count2

{

if(Choice==1)                        //选择变量1调时

{

hour++;

if(hour>=24)

hour=0;

}

if(Choice==2)                        //选择变量2调分

{

min++;

if(min>=60)

min=0;

}

if(Choice==3)                        //选择变量3调秒

{

sec++;

if(sec>=60)

sec=0;

}

if(Choice4==1)                        //选择变量1调时

{

hour4++;

if(hour4>=24)

hour4=0;

}

if(Choice4==2)                        //选择变量2调分

{

min4++;

if(min4>=60)

min4=0;

}

}

count2=0;                                        //count2清0

}

if(!K3)

{

count3++;

if(count3>=key_L)                        //长按

{

if(Choice==1)                        //选择变量

{

hour--;

if(hour>=24)

hour=23;

}

if(Choice==2)                        //选择变量

{

min--;

if(min>=60)

min=59;

}

if(Choice==3)                        //选择变量

{

sec--;

if(sec>=60)

sec=59;

}

if(Choice4==1)                        //选择变量

{

hour4--;

if(hour4>=24)

hour4=23;

}

if(Choice4==2)                        //选择变量

{

min4--;

if(min4>=60)

min4=59;

}

count3=key_M;

}

}

else                                                        //按键抬起

{

if(count3>key_S && count3

{

if(Choice==1)                        //选择变量

{

hour--;

if(hour>=24)

hour=23;

}

if(Choice==2)                        //选择变量

{

min--;

if(min>=60)

min=59;

}

if(Choice==3)                        //选择变量

{

sec--;

if(sec>=60)

sec=59;

}

if(Choice4==1)                        //选择变量

{

hour4--;

if(hour4>=24)

hour4=23;

}

if(Choice4==2)                        //选择变量

{

min4--;

if(min4>=60)

min4=59;

}

}

count3=0;                                        //count3清0

}

if(!K4)                                                        //检测按键1按下

{

count4++;                                        //消抖计数1自+1

if((count4>=key_S)&&(key4_sign==0))//检测消抖计数与按键1自锁标志

{

key4_sign=1;                        //按键1自锁标志置1

Choice4++;                                //调整选择变量自+1

if(Choice4>=4)                        //调整闹钟时间选择0闹钟关闭,1调时,2调分,3开启闹钟

{

Choice4=0;                        //调整时间选择清0

}

}

}

else

{

key4_sign=0;                                //按键1自锁标志清0

count4=0;                                        //消抖计数count1清0

}

}

/************************************

计时子程序

************************************/

void Time()

{

if(TF0==1)                                                //如果查询定时器溢出标志TF0为1

{                                                                //定时器溢出周期100us

TF0=0;                                                //定时器溢出标志TF0清0

Cnt100us++;                                        //时间变量Cnt100us自+1

if((Cnt100us>2500 && Cnt100us<5000)||(Cnt100us>7500 && Cnt100us<10000))//闪烁频率2Hz

Twinkle=1;                                //闪烁标志

else Twinkle=0;

if(Cnt100us>=9982)                    //在此可以按万分之一秒调整精度

{

Cnt100us=0;                                //变量Cnt100us清0

second=1;

if(Choice!=3)                        //调整选择变量为3停止走秒

sec++;                                //秒自+1

if(sec>=60)                                //如果秒>=60

{

sec=0;                                //秒清0

min++;                                //分自+1

if(min>=60)                        //分>=60

{

min=0;                        //分清0

hour++;                  //小时自+1

if(hour>=24)        //小时>=24

hour=0;                //小时清0

}

}

}

}

}

/********************************

数码管显示程序

********************************/

void display()

{

static uchar num=0;                                //分时显示变量

static uchar num1=0;                                //计数延时变量

num1++;

if(num1>=30)                                                //1~255可调,数码管闪烁可减小,有鬼影可加大

{

num1=0;

if((Choice4>0)&&(Choice4<3))

{

switch(num)

{

case 0:

P0=table[hour4/10];        //时十位段码

dula=1;

dula=0;

P0=0x7e;                        //时十位位码

wela=1;

wela=0;

num++;

break;

case 1:

if((Twinkle==1)&&(Choice4==1))//时点闪烁

P0=table[hour4%10];

else

P0=table[hour4%10]|0x80;//时个位段码+点

dula=1;

dula=0;

P0=0x7d;                        //时个位位码

wela=1;

wela=0;

num++;

break;

case 2:

P0=table[min4/10];        //分十位段码

dula=1;

dula=0;

P0=0x7b;                        //分十位位码

wela=1;

wela=0;

num++;

break;

case 3:

if((Twinkle==1)&&(Choice4==2))//分点闪烁

P0=table[min4%10];

else

P0=table[min4%10]|0x80;//分个位段码+点

dula=1;

dula=0;

P0=0x77;                        //分个位位码

wela=1;

wela=0;

num++;

break;

case 4:

P0=0x40;        //秒十位段码

dula=1;

dula=0;

P0=0xef;                        //秒十位位码

wela=1;

wela=0;

num++;

break;

case 5:

P0=0x40;//秒个位段码

dula=1;

dula=0;

P0=0xdf;                        //秒个位位码

wela=1;

wela=0;

num=0;

break;

}

}

else

{

switch(num)

{

case 0:

P0=table[hour/10];        //时十位段码

dula=1;

dula=0;

P0=0x7e;                        //时十位位码

wela=1;

wela=0;

num++;

break;

case 1:

if((Twinkle==1)&&(Choice==1))//时点闪烁

P0=table[hour%10];

else

P0=table[hour%10]|0x80;//时个位段码+点

dula=1;

dula=0;

P0=0x7d;                        //时个位位码

wela=1;

wela=0;

num++;

break;

case 2:

P0=table[min/10];        //分十位段码

dula=1;

dula=0;

P0=0x7b;                        //分十位位码

wela=1;

wela=0;

num++;

break;

case 3:

if((Twinkle==1)&&(Choice==2))//分点闪烁

P0=table[min%10];

else

P0=table[min%10]|0x80;//分个位段码+点

dula=1;

dula=0;

P0=0x77;                        //分个位位码

wela=1;

wela=0;

num++;

break;

case 4:

P0=table[sec/10];        //秒十位段码

dula=1;

dula=0;

P0=0xef;                        //秒十位位码

wela=1;

wela=0;

num++;

break;

case 5:

if(Choice4==3)

P0=table[sec%10]|0x80;//闹钟秒个位+点

else if((Twinkle==1)&&(Choice==3))//秒点闪烁+点

P0=table[sec%10]|0x80;

else

P0=table[sec%10];//秒个位段码

dula=1;

dula=0;

P0=0xdf;                        //秒个位位码

wela=1;

wela=0;

num=0;

break;

}

}

}

}

/********************************

闹钟程序

********************************/

void Buzzer_nz()

{

if((Choice4==3)&&(hour4==hour)&&(min4==min)&&(sec<30))

Buzzer_sign=1;

else Buzzer_sign=0;

if((second==1)&&(Buzzer_sign==1))        //计时周期1s

{

TR1 = 1;                                        //定时器1开,蜂鸣器响一下

second=0;                                        //定时周期1s变量清0

}

}

/********************************

主程序

********************************/

void main(void)

{

Timer_Init();                                        //初始化定时器

while(1)

{

key_scan();                                        //按键扫描

Time();                                                //计时

display();                                        //显示

Buzzer_nz();                                //闹钟

}

}

/*-----------------------------

定时器2中断服务程序  250微秒

(无源蜂鸣器驱动程序)

------------------------------*/

void timer1() interrupt 3

{

static uint count3=0;                        //中断计数变量

count3++;                                                //中断计数变量count3自+1

Buzzer=~Buzzer;                                        //蜂鸣器端口取反

if(count3>=500)                                        //0.1秒时间到500

{

count3=0;                                        //计数清0

Buzzer=1;                                        //蜂鸣器端口清0

TR1 = 0;                                                //定时器1关闭

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值