【说明】本文学习自《单片机原理及应用(张毅刚)》。
目录
1 定时器T0和T1
2 定时器/计数器的4种工作方式
2.1 方式0
2.2 方式1
2.3 方式2
2.4 方式3
2.4.1 工作方式3下的T0
2.4.2 T0工作在方式3下T1的各种工作方式
3 定时器/计数器得编程和应用
3.1 方式1的应用
3.2 方式2的应用
3.3 方式3的应用
3.4 门控制位GATE的应用——测量脉冲宽度
T0和T1是2个独立的16bit向上计数定时器。T0共有4种不同的操作模式:
模式1:13位向上计数定时器;
模式2:16位向上计数定时器;
模式3:8位向上计数寄存器,并指定重装值;
模式4:独立的2个8位向上计数定时器。
T1有2种不同的操作模式:(只有T0的模式1和模式2)
模式1:13位向上计数定时器;
模式2:16位向上计数定时器。
T0和T1分别支持ET0和ET1中断。
当M1、M0为00时,定时器/计数器被设置为工作方式0,这时定时器/计数器的等效框图如图2-1所示(以定时器/计数器T1为例,TMOD.5、TMOD.4 = 00)。
定时器/计数器工作在方式0时,为13位的计数器,由TLX(X=0,1)的低5位和THX的高8位所构成。TLX低5位溢出则向THX进位,THX计数溢出则置位TCON中的溢出标志位TFX。
图2-1中, 位控制的电子开关决定了定时器/计数器的工作模式:
1)电子开关打在上面位置,T1位定时器工作模式,以系统时钟振荡器12分频后的信号作为计数信号。
2) 电子开关打在下面位置,T1为计数器工作模式,计数脉冲为P3.5引脚上的外部输入脉冲,当引脚上发生负跳变时,计数器加1。
GATE位的状态决定定时器/计数器运行控制取决于TRX一个条件还是TRX和引脚这两个条件。
1) GATE=0时,A点(见图2-2)电位恒为1,B点的电位仅取决于状态。,B点为高电平,控制断控制电子开关闭合。计数脉冲加到T1(或T0)引脚,允许T1(或T0)计数。,B点为低电平,电子开关断开,禁止T1(或T0)计数。
2)GATE=1时,B点电位由的输入电平和的状态这两个条件来确定。当,且时(X=0或1),B点才为1,控制端控制电子开关闭合,允许定时器/计数器计数,故这种情况下计数器是否计数是由TRX和 2个条件来控制的。
图2-1 定时器/计数器方式0逻辑结构框图
当M1、M0为01时,定时器/计数器工作于方式1,这时定时器/计数器的等效电路如图2-2所示(以定时器/计数器T1为例)。
方式1和方式0的差别仅仅在于计数器的位数不同,方式1为16位的计数器,由THX作为高8位和TLX作为低8位构成(X-0,1),方式0则为13位计数器,有关控制状态位的含义(GATE、C/T、TFX、TRX)与方式0相同。
图2-2 定时器/计数器方式1逻辑结构框图
方式0和方式1的最大特点是计数溢出后,计数器为全0。因此在循环定时或循环计数应用时就存在反复装入计数初值的问题。这不仅影响定时精度,而且也给程序设计带来麻烦。方式2就是针对此问题而设置的。
当M1、M0为10时,定时器/计数器处于工作方式2,这时定时器/计数器的等效框图如图6-4所示(以定时器T1为例,X=1)。
方式0和方式1的最大特点是计数溢出后,计数器为全0。因此在循环定时或循环计数应用时就存在反复装入计数初值的问题。这不仅影响定时精度,而且也给程序设计带来麻烦。方式2就是针对此问题而设置的。
当M1、M0为10时,定时器/计数器处于工作方式2,这时定时器/计数器的等效框图如图2-3所示(以定时器T1为例,X=1)。
图 2-3 定时器/计数器方式2逻辑结构框图
定时器/计数器的方式2为自动恢复初值的(初值自动装入)8位定时器/计数器,TLX作为常数缓冲器,当TLX计数溢出时,在置1溢出标志TFX的同时,还自动的将THX中的初值送至TLX,使TLX从初值开始重新计数。定时器/计数器的方式2工作过程如图2-4若是(X=0,1)。
这种工作方式可以省去用户软件中重装初值的程序,简化定时初值的计算方法,可以相当精确的确定定时时间。
图 2-4 方式2工作过程
方式3是为了增加1个附加的8位定时器/计数器而提供的,从而使MCS-51具有3个定时器/计数器。方式3只适用与定时器/计数器T0,定时器/计数器T1不能工作在方式3。T1处于方式3相当于TR1=0,停止计数(此时T1可用来作串口波特率产生器)。
当TMOD的低2位位11时,T0的工作方式被选为方式3,各引脚与T0的逻辑关系框图如图2-5所示。
图 2-5 各引脚与T0的逻辑关系
定时器/计数器T0分为2个独立的8位计数器:TL0和TH0,TL0使用T0的状态控制位、GATE、TR0、,而TH0被固定为1个8位定时器(不能为外部计数模式),并使用定时器T1的状态控制位TR1和TF1,同时占用定时器T1的中断请求源TF1。
一般情况下,当T1用作串行口的波特率发生器时,T0才工作在方式3。T0处于工作方式3时,T1可定为方式0、方式1和方式2,用来作为串行口的波特率发生器,或不需要中断的场合。
(i)T1工作在方式0
T1的控制字中M1、M0=00时,T1工作在方式0,工作示意图如图2-6所示。
图 2-6 T0工作在方式3时T1为方式0的工作示意图
(ii)T1工作在方式1
T1的控制字中M1、M0=01时,T1工作在方式1,工作示意图如图2-7所示。
图 2-7 T0工作在方式3时T1为方式1的工作示意图
(iii) T1工作在方式2
T1的控制字中M1、M0=10时,T1的工作方式为方式2,工作示意图如图2-8所示。
图 2-8 T0工作在方式3时T1为方式2的工作示意图
(iv)T1工作在方式3
T1的控制字中M1、M0=11时,T1停止计数。
在T0为方式3时,T1运行的控制条件只有2个,即和M1、M0。选择时定时器模式还是计数器模式,M1、M0选择T1运行的工作方式。
知识补充,在51单片机中,为什么T1不能工作于方式3
51单片机只有T0、T1,没有T2(52才有)。如果工作在方式0、方式1、方式2的话,51单片机T0、T1都可以做波特率发生器(一般时方式2做波特率发生器)。但是T0可以工作在方式3,T1不能工作在方式3。这种情况下,只能用T1作为波特率发生器,T1的字源TF1、TR1给了T0,T0工作在方式3,可以当作定时器、计数器用。而如果用T0做波特率发生器,因为T1不能工作在方式3,方式3就没法用了。
定时器/计数器的4种工作方式中,方式0与方式1基本相同,只是计数器位数不同。方式0为13位计数器,方式1为16位计数器。由于方式0是为兼容MCS-48而设,且其计数初值计算复杂,所以在实际应用中,一般不用方式0,而采用方式1。
例1 假设系统时钟频率采用6MHz,要在P1.0上输出1个周期为2ms的方波,如图3-1所示。
图 3-1
方波的周期用定时器T0来确定,即在T0中设置1个初值,在初值的基础上进行计数,每隔1ms产生1次中断,CPU响应中断后,在中断服务程序中对P1.0引脚信号取反。T0中断入口地址为000BH。为此要做如下几步工作:
(i)计算初值
设:需要装入T0的初值为,则有:
,
化为十六进制,即
。
所以,T0的初值为:
,
(ii)初始化程序设计
本例采用定时器中断方式工作。初始化程序包括定时器初始化和中断系统初始化,主要是对寄存器IP、IE、TCON、TMOD的相应位进行正确的设置,并将计数初值送入定时器中。
(iii)程序设计
中断服务程序除了完成产生要求的方波这一工作之外,还要注意将计数初值重新装入定时器中,为下一次产生中断作准备。主程序可以完成任何其它工作,一般情况下常常是键盘程序和显示程序。在本例中,由于没有这方面得要求,用一条转至自身的短跳指令来代替主程序。
按上述要求设计的参考程序如下:
ORG 0000H
RESET: AJMP MAIN ;转主程序
ORG 000BH ;T0的中断入口
AJMP 1T0P ;转T0中断处理程序1T0P
ORG 0100H
MAIN: MOV SP,# 60H ;设堆栈指针
MOV TMOD,#01H ;设置T0为方式1
ACALL PT0M0 ;调用子程序PT0M0
HERE: AJMP HERE ;自身跳转
PT0M0: MOV TL0,#0CH ;T0中断服务程序,T0重新置初值
MOV TH0,#0FEH
SETB TR0
SETB EA
RET
ITOP: MOV TL0,#0CH ;T0中断服务子程序,T0置初值
MOV TH0,#0FEH
CPL P1.0 ;P1.0的状态取反
RETI
如果CPU不做其它工作,也可以采用查询的方式进行控制,程序要简单的多。
查询方式的参考程序如下:
MOV TMOD,#01H ; 设置T0为方式1
SETB TR0 ; 接通T0
LOOP: MOV TH0, #0FEH ; T0置初值
MOV TL0, #0CH
LOOP1: JNB TF0, LOOP1 ; 查询TF0标志是否为1,如为1,说明T0溢出,则往下执行
CLR TR0 ; T0溢出,关闭T0
CPL P1.0 ; P1.0的状态求反
SJMP LOOP
由上可见,程序虽然简单,但CPU必须得不断查询TF0标志,不能再做其它工作。
例2 假设系统时钟为6MHz,编写定时器T0产生1s定时的程序。
(i)定时器T0工作方式的确定
因定时时间较长,采用哪一种工作方式合适呢?由前面介绍的定时器的个种工作方式的特性可以计算出:
由上可见,可选方式1,每隔100ms中断1次,中断10次为1s。
(ii)计算计数初值
因为:
所以:
因此:
(iii)10次计数的实现
对于中断10次计数,可使T0工作在计数方式,也可用循环程序得方法实现。本例采用循环程序法。
(iv)程序设计
参考程序如下:
ORG 0000H
RESET: LJMP MAIN ;上电,转主程序入口MAIN
ORG 000BH ;T0的中断入口
LJMP IT0P ;转T0中断处理程序IT0P
ORG 1000H
MAIN: MOV SP,#60H ;设堆栈指针
MOV B,#0AH ;设循环次数10次
MOV TMOD,#01H ;设T0工作在方式1
MOV TL0, #B0H ;给T0设初值
MOV TH0,#3CH
SETB TR0 ;启动T0
SETB ET0 ;允许T0中断
SETB EA ;CPU开放中断
HERE: SJMP HERE ;等待中断
ITOP: MOV TL0, #0B0H ;T0中断服务子程序,重新给T0装入初值
MOV TH0, #3CH
DJNZ B, LOOP
CLR TR0 ;1s定时时间到,停止T0工作
LOOP: RETI
方式2是1个可以自动重新装载初值的8为计数器/定时器。这种工作饭是可以省去用户程序中重新装入初值的指令,并可产生相当精确的定时时间。
例3 当T0(P3.4)引脚上发生负跳变时,从P1.0引脚上输出1个周期为1ms的方波。如图3-2所示。(假设系统时钟为6MHz)
图 3-2
(i)工作方式选择
T0定义为方式1计数器模式,T0初值为0FFFFH,即外部计数输入端T0(P3.4)发生1次负跳变时,计数器T0加1且溢出,溢出标志TF0置1,向CPU发出中断请求。在进入T0中断程序后,把F0标志置1,说明T0引脚生已接收里负跳变信号。T1定义为方式2定时器模式。在T0引脚产生1次负跳变后,启动T1每500us产生1次中断,在中断服务程序中对P1.0引脚信号求反,使P1.0产生周期为1ms的方波。(T0和T1定时器进行合作)
(ii)计算T1的初值
设T1的初值为X:
则
(iii)程序设计
ORG 0000H
RESET: LJMP MAIN ;复位入口转主程序
ORG 000BH
LJMP ITOP ;转T0中断服务程序
ORG 001BH
LJMP IT1P ;转T1中断服务程序
ORG 0100H
MAIN: MOV SP, #60H
ACALL PT0M2 ;调用对T0,T1初始化子程序
LOOP: MOV C, F0 ;T0产生过中断了吗?产生过中断,则F0=1
JNC LOOP ;T0没有产生过中断,则跳到LOOP,等待T0中断
SETB TR1 ;启动T1
SETB ET1 ;允许T1中断
HERE: AJMP HERE
PT0M2:MOV TMOD, #26H ;对T1,T0初始化,T1为方式2定时器,T0为方式1计数器
MOV TL0, #0FFH ;T0置初值
MOV TH0, #0FFH
SETB TR0 ;启动T0
SETB ET0 ;允许T0中断
MOV TL1, #06H ;T1置初值
MOV TH1, #06H
CLR F0 ;把T0已发生中断标志F0清0
SETB EA ;CPU开放中断
RET
IT0P: CLR TR0 ;T0中断服务程序,停止T0计数
SETB F0
RETI
IT1P: CPL P1.0 ;T1中断服务程序,P1.0位取反
RETI
在T1定时中断服务程序IT1P中,由于方式2是初值可以自动重新装载的,省去了T1中断服务程序中重新装入初值06H的指令。
例4 例用定时器T1的方式2对外部信号计数,要求每计满100个数,将P1.0引脚信号取反。
本例是方式2计数模式的应用举例。
(i)选择工作方式
外部信号由T1(P3.5)引脚输入,每发生1次负跳变计数器加1,每输入100个脉冲,计数器产生溢出中断,在中断服务程序中将P1.0引脚信号取反1次。
T1工作在方式2的方式控制字位TMOD=60H。不使用T0时,TMOD的低4位可任取,但不能使T0进入方式3,这里取全0。
(ii)计算T1的初值
因此,TL1的初值为9CH,重装初置寄存器TH1=9CH。
(iii)程序设计
ORG 0000H
LJMP MAIN
ORG 001BH ;T1中断服务程序入口
CPL P1.0 ;P1.0位取反
RETI
ORG 0100H
MAIN:MOV TMOD, #60H ;设置T1为方式2计数
MOV TL0, #9CH ;T0置初值
MOV TH0, #9CH
SETB TR1 ;启动T1
HERE: AJMP HERE
方式3对T0和T1大不相同。T0工作在方式3时,T1只能工作在方式0、1、2。T0工作在方式3时,TL0和TH0被分成2个独立的8位定时器/计数器。其中,TL0可作为8位的定时器/计数器;而TH0只能作为8位的定时器。
一般情况下,当定时器T1用作串行口波特率发生器时,T0才设置为方式3。此时,常把定时器T1设置为方式2,用作波特率发生器。
例5 假设某MCS-51应用系统的2个外部中断源已被占用,设置定时器T1工作在方式2,作波特率发生器用。现要求增加1个外部中断源,并控制P1.0引脚输出1个5kHz的方波。假设系统时钟为6MHz。
(i)选择工作方式
由第5章介绍的利用定时器作为外部中断源的思想,设置TL0工作在方式3计数模式,把T0引脚(P3.4)作附加的外部中断输入端,TL0的初值设为0FFH,当检测到T0引脚电平出现负跳变时,TL0溢出,申请中断,这相当于跳沿触发的外部中断源。TH0为8位方式3定时模式,定时控制P1.0输出5kHz的方波信号。如图3-3所示。
图 3-3
(ii)初值计算
TL0的初值设为0FFH。
5kHz方波的周期为200us,因此TH0的定时时间为100us。TH0初值计算如下:
(iii)程序设计
源程序如下:
ORG 0000H
LJMP MAIN
ORG 000BH ;T0中断入口
LJMP TL0INT ;跳T0中断服务程序
ORG 001BH ;注意,在T1为方式3时,TH0占用了T1的中断
LJMP TH0INT ;跳TH0中断服务程序
ORG 0100H
MAIN:MOV TMOD, #27H ;T0为方式3计数,T1为方式2定时
MOV TL0, #0FFH ;置TL0初值
MOV TH0, #9CH ;置TH0初值
MOV TL1, #data1 ;data是根据波特率常数要求来定,见第7章
MOV TH1, #datah
MOV TCON, #55H ;允许T0中断
MOV IE, #9FH ;启动T1
.
.
.
TL0INT:MOV TL0, #0FFH ;TH0中断服务程序,TH0重新装入初值
CPL P1.0 ;P1.0位取反输出
RETI
下面以T1为例,来介绍门控制位GATE1的应用。门控制位GATE1可使定时器/计数器T1的启动计数受的控制,当GATE1 = 1,TR1为1时,只有
引脚输入高电平时,T1才被允许计数,利用GATE1的这个功能,(对于GATE0也是一样,可使T0的启动计数受
的控制),可测量的控制),可测量
引脚(P3.3)上正脉冲的宽度(机器周期数),其方法如图3-4所示。
图 3-4
参考程序如下:
ORG 0000H
RESET: AJMP MAIN ;复位入口转主程序
ORG 0100H
MAIN: MOV SP, #60H
MOV TMOD, #90H ;设控制字,T1为方式1定时
MOV TL1, #00H
MOV TH1, #00H
LOOP: JB P3.3, LOOP ;设控制字,T1为方式1定时
SETB TR1 ;如果$\overline{INT1}$为低,启动T1
LOOP1: JNB P3.3, LOOP1 ;等待$\overline{INT1}$升高
LOOP2: JB P3.3, LOO2 ;等待$\overline{INT1}$降低
CLR TR1 ;停止T1计数
MOV A, TL1 ;T1计数值送A
【将A中的T1计数值送显示缓冲区并转换成可显示的代码】
LOOP3: LCALL DIR ;调用显示子程序DIR(略)显示T1计数值
AJMP LOOP3
执行以上程序,使引脚上出现的正脉冲宽度以机器周期数的形式显示在显示器上。