在实时系统中,定时通常使用定时器,这与软件循环的定时完全不同。虽然两者都是依赖系统时钟,但是在定时器计数时,其它指令可以继续进行,但软件定时时不允许其它任何事件发生。
对许多连续计数和持续时间操作,最好使用16位定时/计数器。当计数器翻转后,它会继续计数。若在计数开始或定时时间间隔开始读出计数器的值,在计数或时间间隔结束时从读出值中减去开始时的读出值,则所得计数数值为其间的计数或持续的时间间隔。假设定时器用于V-F(电压到频率)转换器信号的周期测量。若当逻辑1到来时计数值为3754,下一个逻辑1到达时是4586,则V-F转换器的周期是832个机器周期。使用12MHz晶振为832μs(1.202kHz),使用11.0592MHz晶振,计数值近似903μs(1.071kHz)。当计数值有翻转时,只要计数值以16位无符号整数对待就无算术问题。
例1 设单片机的fosc=12MHz,要求在P1.0脚上输出周期为2ms的方波。
解 周期为2ms的方波要求定时间隔1ms,每次时间到P1.0取反。
定时器计数率=fosc/12。机器周期=12/fosc=1μs
每个机器周期定时器加1,1ms=1000μs
需计数次数=1000/(12/fosc)=1000/1=1000
由于计数器向上计数,所以为得到1000个计数之后的定时器溢出,必须给定时器置初值-1000。
(1)用定时器0的方式1编程,采用查询方式,程序名为time32.c
程序代码如下:
#i nclude
sbit P1_0 = P1^0;
void main(void)
{
TMOD = 0x01; // 定时器0方式1
TR0 = 1; // 启动T/C0
for(;;)
{
TH0 = -(1000/256); // 装载计数初值
TL0 = -(1000%256);
do {} while(!TF0); // 查询等待TF0置位
P1_0 = !P1_0; // 定时时间到,P1.0反相
TF0 = 0; // 软件清TF0
}
}
上面的程序,罗亩已经在Keil uVision中测试成功,但在拷贝时可能因Html代码原因而加入其它字符,所以在拷贝上面的程序时,要注意检查在编辑器中的情况。
扩展阅读:单片机计数器与定时器