51单片机内部一般有两个计数/定时器,T0 T1,其框图如下:
其中TH1 TL1用来设定T1的计数初值,TH0 TL0则用来设定T0的。
一、工作模式设置寄存器TMOD,地址为89H,格式如下图:
1、GATE——门控位
GATE = 0时,仅由运行控制位TRX(X = 0,1) = 1 来启动定时/计数器。
GATE = 1时,由TRX(X = 0 , 1) = 1 和 外中断引脚(INT0 或 INT1)上的高电平共同来启动
2、M1、M0——工作方式选择位
0 0——方式0,为13位定时/计数器;
0 1——方式1,为16位定时/计数器;
1 0——方式2,8位初值自动重装载,将TH和TL分开,TH自动重新装入TL;
1 1——方式2,仅适用于T0,分成两个8位计数器,T1停止工作。
3、C/-T——计数器模式和定时器模式选择位
0——为定时器;1——为计数器,计数器对外部输入引脚(P3.4和P3.5)的外部脉冲(负跳变)计数。
二、控制寄存器TCON,地址为88H~8FH
低四位与外部中断有关。
1、TF1、TF0——T1、T0计数溢出标志位
溢出时由硬件自动将其置1,可以由程序查询,该位确定溢出。非中断模式下,软件清零;中断方式时,此位为中断源,
进入中断服务函数后由硬件自动清零。
2、TR1、TR0——计数运行控制位
1——和GATE位配合(看GATE位设置),启动计数定时器;
0——停止定时/计数器。该位有软件置位或者清0。
工作方式1框图:
三、初值计算
1、机器周期 = 具体晶振频率 / 分频数 的倒数
2、初值 = 溢出值 - 机器周期 * 定时时间
假设T0初值为5000,则应该这么设置:
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
一个编程例子:
TMOD = 0X01; //设置t0为16位(01)计时模式,以TR0来启动计时器
//计算初值
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
EA = 1; //开总中断
ET0 = 1;//开定时器0中断
TR0 = 1; //启动T0
while (1);
定时器中断服务函数;
void timer0_service(void) interrupt 1 (T1 时这里应为3)
{
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256; //打算继续定时下去时,进入中断服务函数后,重新设定一下初值。
times++; //这可以产生更大的定时
if (times == 20) {
times = 0;
led = !led;
}
}