新闻中心

EEPW首页>嵌入式系统>设计应用> 51单片机T0做精确时钟

51单片机T0做精确时钟

作者: 时间:2016-11-19 来源:网络 收藏
T0精确时钟,为了做到尽量精确,必须减少中断的次数,所以选择使用方式1,它最多可以计数65536次。但是,方式1中断后需要重新给定时器赋初值,这样就要耽误几个机器周期,很难保证时钟的精确。

有两个方法可以解决这个问题。

本文引用地址://m.amcfsurvey.com/article/201611/318363.htm

第一个方法:你可以计算出中断处理时重新给定时器赋初值所用的机器周期数,在你计算出的初值里除去这几个机器周期,作为补偿。这个方法,只是在每次定时器中断后,都可以按时得到执行时很精确,但事实上中断什么时候执行谁都说不准,所以这个方法,只能做到尽量精确。

第二个方法:计算出一个凑巧的初值,使TL0正好等于0x00,这样每次中断溢出后,TL0都从0x00开始计数,即使中断没有得到执行,TL0也会继续计数。利用这一点,在中断处理函数中,只需要对TH0重新赋值,不需要管TL0。以下是示例程序:

//定时器T0时钟参数

unsigned char T0_S = 0;//秒

unsigned char T0_M = 0;//分

unsigned char T0_H = 0;//时

unsigned char T0_Cycle = 0;//循环次数

//本程序所用晶振22.1184MHz,每次定时25ms,循环40次正好1s。

void Timer0_Init(void)//T0初始化函数

{

TMOD = 0x01;//设置T0工作方式1

TH0= 0x4c;//(65536-46080)/256,设置初值46080,晶振22.1184MHz,

//每个机器周期0.5425微秒,定时25ms

TL0= 0x00;//(65536-46080)%256,TL0恰好=0x00

IE|= 0x82;//开中断

TR0= 1 ;//T0开始定时

}

//

void Timer0(void)interrupt1

{

TH0= 0x4c;//重新给TH0赋值

//TL0= 0x00;//不对TL0赋值,让其继续计数

TF0= 0 ;//定时溢出清0

T0_Cycle ++ ;

if(T0_Cycle == 40)//循环40次,每次25ms,定时1s

{

T0_Cycle = 0 ;

T0_S++ ;

if(T0_S == 60)

{

T0_S = 0;

T0_M++;

if(T0_M == 60)

{

T0_M = 0;

T0_H++;

if(T0_H == 24)

{

T0_H = 0;

}

}

}

}

}

以上程序即使T0中断赋初值会耽误几个机器周期,中断没有得到及时执行也没有关系,因为TL0的计数不受影响。但有一种情况必须要注意,虽然这种情况发生的可能性不大。如果T0中断长时间没有得到响应,TL0再一次溢出了,这时这种方法的误差就大了。

经过测试,第二种方法还是比较精确的,时钟跑了一天快了10s,这个误差应该是晶振本身的问题,如果是定时器的问题,应该是慢了,不会快了。



评论


技术专区

关闭