51单片机T0做精确时钟51单片机T0做精确时钟
用T0做精确时钟,为了做到尽量精确,必须减少中断的次数,所以选择使用方式1,它最多可以计数65536次。但是,方式1中断后需要重新给定时器赋初值,这样就要耽误几个机器周期,很难保证时钟的精确。 有两个方法可以解决这个问题。
第一个方法:你可以计算出中断处理时重新给定时器赋初值所用的机器周期数,在你计算出的初值里除去这几个机器周期,作为补偿。这个方法,只是在每次定时器中断后,都可以按时得到执行时很精确,但事实上中断什么时候执行谁都说不准,所以这个方法,只能做到尽量精确。
第二个方法:计算出一个凑巧...
51单片机T0做精确时钟
用T0做精确时钟,为了做到尽量精确,必须减少中断的次数,所以选择使用方式1,它最多可以计数65536次。但是,方式1中断后需要重新给定时器赋初值,这样就要耽误几个机器周期,很难保证时钟的精确。 有两个
可以解决这个问
。
第一个方法:你可以计算出中断处理时重新给定时器赋初值所用的机器周期数,在你计算出的初值里除去这几个机器周期,作为补偿。这个方法,只是在每次定时器中断后,都可以按时得到执行时很精确,但事实上中断什么时候执行谁都说不准,所以这个方法,只能做到尽量精确。
第二个方法:计算出一个凑巧的初值,使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。
//22.1184/12*1000*25=46080
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) interrupt 1
{
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,这个误差应该是晶振本身的问题,如果
是定时器的问题,应该是慢了,不会快了。
本文档为【51单片机T0做精确时钟】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。