我们已经实现了用多位数码管计数显示的问题。以下,我们来研究定时计数的问题,即显示时间的问题。在单片机中具有定时器的功能,当然,需要编程才能实现定时,并且有一点复杂。与前面介绍的外部中断功能一样,也是通过设置寄存器来规定单片机状态的。在介绍外部中断时,我们已经知道,定时/计数的中断编号是1和3,即定时/计数中断处理程序的头部必须是interrupt 1或interrupt 3。除此之外,还需要知道什么呢?我们先看一下单片机定时器的结构如图6-3所示。
1)内设2个16位可编程定时/计数器T0,T1;
2)具有计数方式和定时方式;
3)4种工作模式。
图6-3 单片机定时器结构图
再看一下中断请求控制寄存器TCON的定义见表6-2。
表6-2 中断请求控制寄存器TCON的定义
1)高4位定时计数,低4位外部中断。
2)TF1:当T1被允许计数后,从初值开始加1计数,至最高位溢出,TF1置1,表示中断请求。CPU响应中断请求后对TF1清零。
3)TR1:定时计数器控制位,TR1=1启动T1运行,TR1=0时则T1停止运行。
4)TF0:T0溢出标志,意义同TF1。
5)TR0:T0运行控制位,意义同TR1。
工作方式控制寄存器TMOD的定义见表6-3。
表6-3 工作方式控制寄存器TMOD的定义
1)TMOD高4位对T1,低4位对T0;
2)M1,M0:工作方式选择;
3)C/T:计数/定时方式选择位;
■ C/T=1对外部事件脉冲计数,负脉冲有效;
■ C/T=0对片内机器周期脉冲计数,作定时器;
4)GATE:门控位;
■ GATE=0只受TCON中TR的控制;
■ GATE=1同时受TR和外中断输入信号双重控制;
例1:设置定时器T1,工作方式1
TMOD=0x10;
例2:设置定时器T0,工作方式2
TMOD=0x02;
工作方式选择列表见表6-4。
表6-4 工作方式选择
1)工作方式0:13位计数结构,TH全部8位,TL低5位,TL的高3位未使用。中断后计数清零,需重新设置。
2)工作方式1:16位计数结构,TH和TL均为8位。中断同上。
3)工作方式2:具有自动装载功能,TL0为计数器,TH0为预置寄存器,计数结构只有8位。(www.xing528.com)
4)工作方式3:2个独立的8位计数器,TL0既可作计数器,也可作定时器。TH0只能作定时器。
要使用定时器,首先要计算定时器的初值,计算公式和一般方法如下:
1)T(初值)=2N-定时时间/机器周期时间
2)N与工作方式有关
■ 方式0 N=13
■ 方式1 N=16
■ 方式2、3 N=8
3)1机器周期时间=12/fosc=12/12MHz=1μs
例:晶振12MHz,求方式1,T0定时0.2ms初值
216-200/1=65536-200=FF38H
则,高位TH0=FFH,低位TL0=38H
看了以上材料,你是否觉得定时器太复杂了。不要着急,看一下实例,然后对照前面介绍的表格,很快就能熟悉它的用法。
例:用T0,方式1,计时0.05s,设计一个发光二极管闪烁(0.05s开关一次)程序。
计算初值
■ 高位TH0=-50000/256;
■ 低位TL0=-50000%256;
为什么不用216-50000呢?因为-50000的补码等于216-50000
定时计数器0的中断号为1,所以,定时器的中断处理子程序头部为
■ Void intsrv1(void)interrupt 1 using 1
■ 中断后需重新定义初值(方式0,1)
主程序和中断处理子程序如下:
这个程序定义了一个发光二极管引脚LED。在主程序中设置定时器寄存器参数,首先是开总允许中断EA=1和分允许中断ET0=1(定时器0中断)。然后设置定时器工作方式TMOD=0x01,即T0工作方式1。接着是设置定时器T0的初值,高八位TH0和低八位TL0。这里采用前面介绍的数字分离技术,因为8位28=256,所以高8位用-5000/256得到,低8位用-5000%256得到。其中-5000与216-5000结果是一样的。最后是启动定时器0即TR0=1,停止定时器就是TR0=0。然后,主程序就进入一个无限循环。等待定时到,执行中断处理子程序。因此,主程序中没有什么动作,所有操作都是定时到后中断处理子程序进行的操作,即重新定义初值(因为工作方式1定时到后初值自动消失,需要重新定义),和改变发光二极管引脚的电平,使它闪烁。
下面我们就操作电路,编译执行这个程序。元器件列表见表6-5。
表6-5 元器件选择列表
图6-4 0.05s闪烁一次
编译程序,在单片机上加载程序,可看到发光二极管0.05s的闪烁,如图6-4所示。由于间隔时间很短,发光二极管闪烁的很快。如何能使得间隔时间长一点呢?这就需要把定时器初值设的大一点,但是,最大也不能超过216,即65536,也就65536μs=0.065536s。如果要设置成1s闪烁一次该怎么办呢?
显然,定时器初值设置成1s是不可能的,只有另外设置变量来延长定时时间。我们修改一下中断处理程序如下:
在程序头部加上一个全局变量t,定义为unsigned char t;,作为中断子程序的中间变量。每次定时器时间到,处理中断时,给变量t加1,若t=20,就是0.05s×20=1s。即每次0.05s时间到中断时并不执行发光二极管电平取反,直到20次时,就是1s时,才执行一次。这样就实现了定时1s的功能。重新编译程序,执行仿真运行,看是不是1s闪烁一次?
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。