(周振安)这一讲我们将学习有关8031单片机定时/计数器的原理,并进行有关实验。
定时/计数器的原理
8031单片机的2个16位可编程定时/计数器,即定时/计数器0和定时/计数器1,实际上都是8031单片机片内RAM区中的存储单元。对于定时/计数器0来讲,它由高位字节单元TH0和低位字节单元TL0一同构成,TH0是片内RAM中的8CH单元,TL0则是8AH单元。定时/计数器1由高位字节单元TH1和低位字节单元TL1联合构成,TH1和TL1分别是片内RAM中的8DH和8BH(请参见讲座第五讲的表1)。在定时/计数器x(即THx+TLx,x=0或1)中置入一个数据作为定时或计数的初值。当定时/计数器x被专用寄存器TMOD中的C/T-位设置为定时器功能(见1条)并被专用寄存器TCON中的TRx位启动运行后(见2条),THx+TLx中内容会在每个机器周期(即晶振周期的12倍)到来时加1(即由片内时钟脉冲触发);当THx+TLx中内容加到2\(^{16}\)(FFFFH,16位定时/计数器)后再来一个内部时钟脉冲就会导致溢出,这时发出中断请求信号使TCON寄存器中的中断标志位TFx置为1(见2条)。当定时/计数器x被TMOD内容设置为计数器功能并被TCON的TRx位启动后,每当8031单片机的0T(或1T)脚输入的外部信号有一个从1到0的跳变时,THx+TLx内容便会加1(即被外部脉冲触发);当加到FFFFH值(指16位定时/计数器)后如再有一个外部脉冲信号到来,则产生溢出,此时发出中断请求信号使TCON中的TFx位置为1。
从上面内容可以看出,定时/计数器x的定时或计数功能选择由TMOD寄存器决定,而中断请求标志及定时/计数器x的启动运行又与TCON有关。下面介绍专用寄存器TMOD和TCON。
1.功能选择及工作方式控制专用寄存器TMOD:
专用寄存器TMOD各位定义如下:

高4位控制定时/计数器1,低4位控制定时/计数器0。M1、M0用来设定定时/计数器的工作方式,当M1,M0排列为00、01、10、11时,分别决定工作方式为0、1、2、3。关于工作方式0~3将在3条中详细介绍。C/T-位为定时/计数器功能选择位,当 C/T-=0时,为定时器功能;当C/T-=1时为计数器功能。GATE为门控位,用于控制定时/计数器x的启动是否与外部中断源0INT-、1INT-有关。当GATE=0时,定时/计数器x的启动与外部中断源无关,即只要TRx=1,定时/计数器x就可以启动工作;当GATE=1时,只有在没有外部中断(即0INT-或1INT-为高电平)时,才允许TRx置1启动定时/计数器x工作。这个意思也可以表示为,当GATE=1时,如TRx=1,定时/计数器x是否启动工作还取决于xINT-(x=0或1),当xINT-由0→1跳变时,定时计数器x才开始工作;当xINT-由1→0时,定时/计数器x停止工作。
2.定时/计数器中断标志及启动控制寄存器TCON:
专用寄存器TCON在上一讲中断内容中已有所介绍,这里再介绍与定时/计数器有关的高4位如下:

其中TF1、TF0分别为定时/计数器1和0的中断标志位,当定时/计数器发生溢出时,相应的标志位置1。TR1,TR0分别为定时/计数器1和0的运行启动控制位,当TR1(或TR0)为1时,定时/计数器1(或0)被启动运行;当TR1(或TR0)为0时,定时/计数器1(或0)停止运行。
3.定时/计数器工作方式介绍:
①工作方式0:在这种工作方式下,THx+TLx的16位只用了13位,TLx的高3位未用。
②工作方式1:这时定时/计数器x的16位全部运行。
③工作方式2:亦称自动恢复初值的8位定时/计数器工作方式。在这种工作方式下,THx用作存放一个常数,由程序预先放置初值常数;TLx用作8位定时/计数器,当它发生溢出时,除中断标志位TFx置1外,还自动将THx中的常数重新装入TLx中作为下一次定时或计数的初值。重装后,THx中内容仍然保持不变。
④工作方式3:工作方式3只对定时/计数器0而言,定时/计数器1无此工作方式。在此工作方式下,16位定时/计数器0分成2个8位定时/计数器TH0和TL0。TL0可工作于定时/计数状态,仍然使用原来的专用寄存器TMOD和TCON中的控制位;而TH0只能用作定时器,它使用了定时/计数器1原来的控制位TR1和TF1。一般地,只有当定时/计数器1不使用控制位TR1和TF1(如作为串行口波特率发生器)时,定时/计数器0才定义为工作方式3,用以增加一个8位定时器(即TH0)。
练习实验
[实验1]利用定时/计数器0的工作方式0,①使定时/计数器0产生1ms定时,②使0P1端输出一个周期为2ms的方波。
我们首先计算定时初值。定时/计数器0工作于方式1时,只有13位参与加1运算。当我们设置了一个定时初值X,则它加到2\(^{13}\)时再来一个内部时钟脉冲就会产生溢出,即过了213-X个时钟周期(设晶振频率为6MHz,时钟周期为12/6MHz=2×10\(^{-}\)6S=2μs)会产生溢出。故要产生1ms定时则有1ms=(213-X)×2μs,解得X=7692。换算为16进制数的方法是:设16进制数为ABCDH,则A=|X/16\(^{3}\)|,B=|(X-A×163)/16\(^{2}\)|,C=|(X-A×163-B×16\(^{2}\))/16|,D=|X—A×163-B×16\(^{2}\)-C×16|。“|…|”表示取整操作,如A=|7692/4096|=|1+3596/4096|=1,B=|3596/256|=|14+12/256|=14(即E-H),C=|12/16|=0,D=12(即CH),故7692的16进制数为1E0CH,即2进制数1111000001100B,TH0+TL0的高8位放11110000,低5位放01100。
由于8031单片机复位后TMOD=00H,中断允许控制字IE也为00H,故程序不必送控制字了。参考程序如下:

请查出程序机器码并输入学习(开发)机,运行后用示波器观察0P1端的波形。如无示波器,可将0P1端串一扬声器接至+5V电源端,运行程序后,通过听声音判断0P1端的频率变化。
[实验2]利用定时/计数器0的工作方式2实现计数功能。实验程序如下:
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP SER
ORG 0100H
MAIN:MOV TMOD,#06H;设置计数功能方式2
MOV IE,#82H;开中断
MOV TH0,#00H;送常数(即定时初值)
MOV TL0,#00H;送第一次计数初值
SETB TR0;启动计数
LOOP:MOV P1,TL0;显示计数值
SJMP LOOP(rel=FCH)
SER: NOP 定时/计数器0的
SJMP LOOP(rel=F9H) 中断服务程序
查出机器码并输入到TD-Ⅰ型机中,然后运行。用一根导线将8031单片机的0T(第14)脚与地线短接,每短接一次相当于0T端电平有一个由1→0的跳变。程序采取的中断方式,比上例的查询方式显然要节省CPU的时间。从本例看,启动计数后,CPU可继续执行LOOP以后的程序,而不必象上例那样原地等待着定时/计数器0中断的到来。本例中一旦走时/计数器0产生中断请求,则由中断服务程序SER进行响应。在实际应用中,有时利用工作方式2,在TLx中装入初值FFH,这样一旦0T(或1T)端有1→0跳变,就会溢出并发出中断请求,从而相当于增加了一个外部中断源0T(或1T)。
[实验3] 利用定时/计数器0的门控位GATE测量脉冲宽度。
当GATE=1,且TR0=1时,若外部中断源引脚0INT-电平为1,则启动定时/计数器0的定时功能开始运行;当0INT-电平为0时,定时停止。利用这一特点,可测量脉冲的宽度。实验程序如下:

查出程序机器码并输入TD-Ⅰ型机,然后从0INT-(12)脚输入一方波脉冲,运行上述程序,最后停止。读出0051H、0050H单元中的高、低8位数据(如ABCDH),换算为10进制数(即A×16\(^{3}\)+B×162+C×16+D),然后乘以2μs就是所测脉冲的宽度。手头没有脉冲发生器时,可从地线引出低电平信号,经过一按钮开关接至0INT-端。运行上述程序后,迅速按动按钮两下(间隔不大于131ms,即2\(^{16}\)×2μs)即可。
[实验4]时钟程序练习。
利用单片和定时/计数器0产生100ms定时,每100ms定时满后产生的中断使B040H单元(在此称为100毫秒累计单元)内容加1;100毫秒单元内容加1十次,则产生1秒的定时,每产生一次1秒钟定时,B041H单元(称为秒单元)内容加1;秒单元内容加1六十次产生1分钟定时,每产生一次1分钟定时,B042H单元(称为分单元)内容加1;每60个分单元内容加1,产生1小时定时,B043H单元(称为时单元)内容加1,从而实现24小时时钟。这些时钟单元内容均以BCD码表示。100ms中断服务子程序如下(由于TD-Ⅰ型机无数码管,实验在TD-Ⅲ型机上进行)

上述子程序对定时/计数器0每100ms产生的中断请求信号进行响应,并产生秒、分、时的数值。定时初值设置、启动、显示秒、分、时由下面的时钟主程序完成。
