如果单片机定时器精度和最长时间都是由晶振、指令周期、定时器的长度决定的。指令周期在某种角度上来说与晶振是同一个意义。因为在C51的MCU一般都是12个时钟周期。如果晶振是12MHZ,那是时钟周期是0.083333uS,0.083333uS*12=1uS。也就是12个时钟轴周期是1uS。定时器寄存器自增1就是一个指令周期。如果您需要一个20mS的定时器,初值应该怎样设定呢?其实就是65536-20000=0xB1E0。
换算为任意晶振,公式就是 vaue=65536-T/( (1/f) *12)。如果vaue的值是负数,那么就说明您的系统无法做到该周期的定时。比如在12M的晶振情况下,如果您将T设计为70mS。value的值就会出现负数。您的系统是设计不了该定时周期的。
/*************************************/
定时器初始化 ,1微秒中断
/*************************************/
void Timer0_Init( )
{
TMOD = TMOD | 0x01;
TH0 = 0xFC;
TL0 = 0x66;
EA =1;
ET0 =1;
TR0 =1;
}
/*************************************/
//定时器串口中断程序
/*************************************/
void Timer0_isr( ) interrupt 1
{
TH0 = 0xFC;
TL0 = 0x66;
//系统代码
}
以上就是我在一个项目使用的代码。 我使用的是7.3278M的晶振。1mS的计时是有误差的。这是我使用一个“单片机”小软件告诉我。具体多少误差您可以自己算算。Timer0_Init( )是定时器0的初始化函数。将定时器0配置为1mS一次中断。TMOD = TMOD | 0x01是设置定时器0为16位计时方式,置EA、ET0分别是使能全部中断、使能定时器0中断。置位TR0开始启动计时。 当 TH0 、 TL0的值都为 0xFF时。系统会产生中断,进行中断处理。 如果们计划在主程序中每20mS处理一件事情,比如刷屏。程序可能是这样写的。
unsigned char refreshLCDCount=0;
void Timer0_Init( )
{
TMOD = TMOD | 0x01;
TH0 = 0xFC;
TL0 = 0x66;
EA =1;
ET0 =1;
TR0 =1;
}
/*************************************/
//定时器串口中断程序
/*************************************/
void Timer0_isr( ) interrupt 1
{
TH0 = 0xFC;
TL0 = 0x66;
//系统代码
if(refreshLCDCount<20)
{
refreshLCDCount++;
}
}
void main( )
{
Timer0_Init( );
while(1)
{
if(refreshLCDCount>=20)
{
//刷新屏幕
refreshLCD( );
refreshLCDCount=0;
}
//MCU休眠,进入低功耗状态!
MCUDormant( );
}
}
在while(1)循环中,if语句检查是否有20mS计时,如果计时达到,那么刷新lcd显示,refreshLCDCount清零。然后MCU进入休眠。定时器中断会唤醒MCU的。