通过前面的定时器理论了解到,使用一个定时器,要经过下面四步:
1、设置定时器/计数器的工作模式TMOD(常用的是模式1:TMOD=0x01);
2、装入预置数到THx和TLx中(THx=TLx=MAX(8192/65536/256)-计数次数);
3、如果工作在中断方式,则需要开定时器/计数器的中断TCON中的标志位:TF0/TF1=0/1;
4、启动定时器/计数器:TR0/TR1=1;
//1、设置定时器/计数器的工作模式TMOD(常用的是模式1:TMOD=0x01); //2、装入预置数到THx和TLx中(THx=TLx=MAX(8192/65536/256)-计数次数); //3、如果工作在中断方式,则需要开定时器/计数器的中断TCON中的标志位:TF0/TF1=0/1; //4、启动定时器/计数器:TR0/TR1=1; // 内容:通过定时让LED灯闪烁 #include<reg52.h> sbit LED=P0^2; //定义LED端口 //定时器初始化子程序 void Init_Timer0(void) { TMOD = 0x01; //使用模式1,16位定时器 TH0=0x00; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出 TL0=0x00; EA=1; //总中断打开 89C52必需要有 ET0=1; //定时器中断打开 TR0=1; //使用定时器0 } main()//主程序 { Init_Timer0(); while(1); } //定时器中断子程序 //interrupt和using都是C51的关键字。C51中断过程通过使用interrupt关键字和中断号(0到31)来实现。 //using关键字用来指定中断服务程序使用的寄存器组。 //用法是:using后跟一个0到3的数,对应着4组工作寄存器。 void Timer0_isr(void) interrupt 1 using 1 { TH0=0x00; //重新赋值 TL0=0x00; LED=~LED; //指示灯反相,可以看到闪烁 }
65536 * 1us = 65.536ms,也就是说上面的程序每经过65.536ms改变P0^2的状态。
那么如何实现1s的精确定时呢,在工作方式1下,我们将计数初什设置为0x3CB0(15536),当计数到上限65536时,经过了50000个脉冲,即 50000 * 1us = 50ms,如果经过这样的计时20次,就正好达到了1s,为验证是否正确,可将上面的代码修改如下:
//1、设置定时器/计数器的工作模式TMOD(常用的是模式1:TMOD=0x01); //2、装入预置数到THx和TLx中(THx=TLx=MAX(8192/65536/256)-计数次数); //3、如果工作在中断方式,则需要开定时器/计数器的中断TCON中的标志位:TF0/TF1=0/1; //4、启动定时器/计数器:TR0/TR1=1; // 内容:通过定时让LED灯闪烁 #include<reg52.h> sbit LED=P0^2; //定义LED端口 unsigned int tm=0; //定时器初始化子程序 void Init_Timer0(void) { TMOD = 0x01; //使用模式1,16位定时器 TH0=0x3C; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出 TL0=0xB0; EA=1; //总中断打开 89C52必需要有 ET0=1; //定时器中断打开 TR0=1; //使用定时器0 } main()//主程序 { Init_Timer0(); while(1); } //定时器中断子程序 //interrupt和using都是C51的关键字。C51中断过程通过使用interrupt关键字和中断号(0到31)来实现。 //using关键字用来指定中断服务程序使用的寄存器组。 //用法是:using后跟一个0到3的数,对应着4组工作寄存器。 void Timer0_isr(void) interrupt 1 using 1 { TH0=0x3C; //重新赋值 3CB0 = 15536 TL0=0xB0; tm = tm + 1; if (tm == 20) // 20次达到1s { tm = 0; LED=~LED; //指示灯反相,可以看到闪烁 } }
编译下载到单片机后,测试和预期一致,LED亮灭的状态分别持续1s。