一. 定时/计数器的初始化
初始化程序应完成如下工作:1). 对TMOD赋值, 以确定T0和T1的工作方式.
2). 计算初值, 并将其写入 TH0, TL0 或者 TH1, TL1.
3). 使用中断方式时, 则对IE赋值, 开放中断.
4). 使 TR0 或 TR1 置位, 启动定时/计数器的定时或计数.
二. 初值的计算
假设定时器工作在方式1, 则位数是16位. 定时器一旦启动, 便在原来的数值上开始加1计数. 如果程序开始时, 我们没有设置TH.x和TL.x, 则它们的默认值为0. 假设时钟频率为12MHz, 12个时钟周期为一个机器周期, 那么此时机器周期就是1us, 计满TH.x 和TL.x 就需要: 计数最大值-1; 再来一个脉冲, 计数器就会溢出, 随即向CPU申请中断. 因此溢出共需要65536us, 约等于65.5ms.例如要定时50ms, 那么就要先给TH.x和TL.x装初值. TH.x和TL.x 中应该装入的总数是65536 - 50000 = 15536; TH.x = 15536 / 256 = 60; TL.x = 15536 % 256 = 176; 在这个初值的基础上级50000个数后就溢出, 此时刚好就是50ms中断一次.
例如要定时1s, 但是定时/计数器的最大定时时长为65536us, 不够. 那么我们可以设定定时50ms, 重复20次, 就刚好是1s了.(20次50ms就刚好是1s).
三. 例子代码
// P1口大约1s置反一次
#include<reg52.h> // 包含特殊功能寄存器的定义
#define LED P1 // 宏定义LED代表P1
unsigned char ucCount = 0;
// 定时器初始化子程序
void Init_Timer0(void)
{
TMOD = 0x01; // 不影响定时计数器T1
// 使用定时计数器T0(GATE 0, C/T 0, M1 0, M0 1)
// 使用模式1, 16位定时器.
TH0 = (65536 - 50000) / 256; // 计数器计数初值, 这里使用定时器最大值从0开始计数一直到65535溢出
TL0 = (65536 - 50000) % 256;
EA = 1; // 总中断打开
ET0 = 1; // 定时器中断打开
TR0 = 1; // 定时器开关打开
}
void main()
{
Init_Timer0();
P1 = 0xFF;
while(1);
}
// 中断函数
void Timer0_isr(void) interrupt 1 using 1
{
TH0 = (65536 - 50000) / 256; // 计数器计数初值, 这里使用定时器最大值从0开始计数一直到65535溢出
TL0 = (65536 - 50000) % 256;
++ucCount;
if(19 == ucCount)
{
LED = ~LED; // 指示灯反相,可以看到闪烁
ucCount = 0;
}
}