用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。
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,这个夺冠应该是晶振自身的问题,假如是守时器的问题,应该是慢了,不会快了。