51单片机T0做精确时钟
有两个方法可以解决这个问题。
第一个方法:你可以计算出中断处理时重新给定时器赋初值所用的机器周期数,在你计算出的初值里除去这几个机器周期,作为补偿。这个方法,只是在每次定时器中断后,都可以按时得到执行时很精确,但事实上中断什么时候执行谁都说不准,所以这个方法,只能做到尽量精确。
第二个方法:计算出一个凑巧的初值,使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) 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精确时 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)