1、第7章 定时器/计数器MCS-51单片机内部有两个16位可编程的定时器/计数器,即定时器T0和定时器T1(8052提供3个,这第三个称定时器T2)。它们既可用作定时器方式,又可用作计数器方式。7 . 1定时器/计数器结构定时器/计数器的基本部件是两个8位的计数器(其中TH1,TL1是T1的计数器,TH0,TL0是T0的计数器)拼装而成。在作定时器使用时,输入的时钟脉冲是由晶体振荡器的输出经12分频后得到的,所以定时器也可看作是对计算机机器周期的计数器(因为每个机器周期包含12个振荡周期,故每一个机器周期定时器加1,可以把输入的时钟脉冲看成机器周期信号)。故其频率为晶振频率的1/12。如果晶振频
2、率为12MHZ,则定时器每接收一个输入脉冲的时间为1us。当它用作对外部事件计数时,接相应的外部输入引脚T0(P3.4)或T1(P3.5)。在这种情况下,当检测到输入引脚上的电平由高跳变到低时,计数器就加1(它在每个机器周期的S5P2时采样外部输入,当采样值在这个机器周期为高,在下一个机器周期为低时,则计数器加1)。加1操作发生在检测到这种跳变后的一个机器周期中的S3P1,因此需要两个机器周期来识别一个从“1”到“0”的跳变,故最高计数频率为晶振频率的1/24。这就要求输入信号的电平要在跳变后至少应在一个机器周期内保持不变,以保证在给定的电平再次变化前至少被采样一次。定时器/计数器有四种工作方
3、式,其工作方式的选择及控制都由两个特殊功能寄存器(TMOD和TCON)的内容来决定。用指令改变TMOD或TCON的内容后,则在下一条指令的第一个机器周期的S1P1时起作用。1、 定时器的方式寄存器TMOD D7 D6 D5 D4 D3 D2 D1 D0GATEC/M1M0GATEC/M1M0 T1方式控制字 T1方式控制字 图7-1 TMOD寄存器各位定义特殊功能寄存器TMOD为定时器的方式控制寄存器,寄存器中每位的定义如图7-1所示。高4位用于定时器1,低4位用于定时器0。其中M1,M0用来确定所选的工作方式,如表7-1所示。 M1 M0 定时器/计数器四种工作方式选择,见表7-1所示。 表
4、7-1 工作方式选择表M1 M0方 式说 明0 0013位定时器/计数器0 1116位定时器/计数器1 02自动装入时间常数的8位定时器/计数器1 13对T0分为两个8位独立计数器;对T1置方式3时停止工作(无中断重装8位计数器) C/ 定时器方式或计数器方式选择位。C/=1时,为计数器方式;C/=0时,为定时器方式。 GATE 定时器/计数器运行控制位,用来确定对应的外部中断请求引脚(,)是否参与T0或T1的操作控制。当GATE=0时,只要定时器控制寄存器TCON中的TR0(或TR1)被置1时,T0(或T1)被允许开始计数(TCON各位含义见后面叙述);当GATE=1时,不仅要TCON中的T
5、R0或TR1置位,还需要P3口的或引脚为高电平,才允许计数。2、 定时器控制寄存器TCON特殊功能寄存器TCON用于控制定时器的操作及对定时器中断的控制。其各位定义如图7-2所示。其中D0D3位与外部中断有关,已在中断系统一节中介绍。 D7 D6 D5 D4 D3 D2 D1 D0TF1TR1TF0TR0IE1IT1IE0IT0 用于外部中断 图7-2 TCON寄存器各位定义 TR0 T0的运行控制位。该位置1或清0用来实现启动计数或停止计数。 TF0 T0的溢出中断标志位。当T0计数溢出时由硬件自动置1;在CPU中断处理时由硬件清为0。 TR1 T1的运行控制位,功能同TR0。 TF1 T1
6、的溢出中断标志位,功能同TF0。 TMOD和TCON寄存器在复位时其每一位均清零。7 . 2 工作方式 如前所述,MCS-51片内的定时器/计数器可以通过对特殊功能寄存器TMOD中的控制位C/的设置来选择定时器方式或计数器方式;通过对M1M0两位的设置来选择四种工作方式,现以T0为例加以说明。1、 方式0 当M1M0设置为00时,定时器选定为方式0工作。在这种方式下,16位寄存器只用了13位,TL0的高三位未用。由TH0的8位和TL0的低5位组成一个13位计数器。 当GATE=0时,只要TCON中的TR0为1,TL0及TH0组成的13位计数器就开始计数;当GATE=1时,此时仅TR0=1仍不能
7、使计数器计数,还需要引脚为1才能使计数器工作。由此可知,当GATE=1和TR0=1时,TH0+TL0是否计数取决于引脚的信号,当由0变1时,开始计数;当由1变0时,停止计数,这样就可以用来测量在端出现的脉冲宽度。 当13位计数器从0或设定的初值,加1到全“1”以后,再加1就产生溢出。这时,置TCON的TF0位为1,同时把计数器变为全“0”。2、 方式1 方式1和方式0的工作相同,唯一的差别是TH0和TL0组成一个16位计数器。3、 方式2 方式2把TL0配置成一个可以自动恢复初值(初始常数自动重新装入)的8位计数器,TH0作为常数缓冲器, TH0由软件预置值。当TL0产生溢出时,一方面使溢出标
8、志TF0置1,同时把TH0中的8位数据重新装入TL0中。 方式2常用于定时控制。例如希望每隔250s产生一个定时控制脉冲,则可以采用12MHz的振荡器,把TH0预置为6,并使C/=0就能实现。方式2不用作串行口波特率发生器。4、 方式3 方式3对定时器T0和定时器T1是不相同的。若T1设置为方式3,则停止工作(其效果与TR1=0相同)。所以方式3只适用于T0。 方式3使MCS-51具有三个定时器/计数器(增加了一个附加的8位定时器/计数器)。当T0设置为方式3时,将使TL0和TH0成为两个相互独立的8位计数器, TL0利用了T0本身的一些控制(C/,GATE,TR0,和TF0)方式,它的操作与
9、方式0和方式1类似。而TH0被规定为用作定时器功能,对机器周期计数,并借用了T1的控制位TR1和TF1。在这种情况下TH0控制了T1的中断。这时T1还可以设置为方式02,用于任何不需要中断控制的场合,或用作串行口的波特率发生器。通常,当T1用作串行口波特率发生器时,T0才定义为方式3,以增加一个8位计数器。7 . 3 定时器/计数器的初始化 1、初始化步骤MCS-51内部定时器/计数器是可编程序的,其工作方式和工作过程均可由MCS-51通过程序对它进行设定和控制。因此,MCS-51在定时器/计数器工作前必须先对它进行初始化。初始化步骤为:(1) 根据题目要求先给定时器方式寄存器TMOD送一个方
10、式控制字,以设定定时器/计数器的相应工作方式。(2) 根据实际需要给定时器/计数器选送定时器初值或计数器初值,以确实需要定时的时间和需要记数的初值。(3) 根据需要给中断允许寄存器IE选送中断控制字和给中断优先级寄存器IP选送中断优先级字,以开放相应中断和设定中断优先级。(4) 给定时器控制寄存器TCON送命令字,以启动或禁止定时器/计数器的运行。2、计数器初值的计算定时器/计数器可用软件随时随地起动和关闭,起动时它就自动加“1”记数,一直记到满,即全为“1”,若不停止,计数值从全“1”变为全“0”,同时将计数溢出位置“1”并向CPU发出定时器溢出中断申请。对于各种不同的工作方式最大的定时时间
11、和计数数不同。这里在使用中就会出现两个问题:一是要产生比定时器最大的定时时间还要小的时间和计数器最大计数次数还要小的计数次数怎么办?二是要产生比定时器最大的定时时间还要大的时间和计数器最大计数次数还要大的计数次数怎么办?解决以上第一个问题只要给定时器/计数器一个非零初值,开定时器/计数器时,定时器/计数器不从0开始,而是从初值开始,这样就可得到比定时器/计数器最大的定时时间和计数次数还要小的时间和计数次数,解决第二个问题就要用到循环程序了,循环几次就相当于乘几。例如要产生1秒的定时你可先用定时器产生50MS的定时,再循环20次就行了,因为1S=1000MS,也可用其它的组合。有时也可采用中断来
12、实现。由上可见,解决问题的基本出路在于初值的计算,下面就来具体讨论计数器的初值计算和最大值的计算。我们把计数器从初值开始作加1计数到计满为全1所需要的计数值设定为C和计数初值设定为D,由此便可得到如下的计算通式: D=M-C (1)式中,M为计数器模值,该值和计数器工作方式有关。在方式0时M为213;在方式1时M为216;在方式2和方式3时M为28。3、定时器初值的计算在定时器模式下,计数器由单片机脉冲经12分频后计数。因此,定时器定时时间T的计算公式为:T=(TMTC)12/fOSC (s) (2)式中TM为计数器从初值开始作加1计数到计满为全1所需要的时间,TM为模值,和定时器的工作方式有
13、关;fOSC是单片机晶体振荡器的频率,TC为定时器的定时初值。在式(2)中,若设TC=0,则定时器定时时间为最大(初值为0,计数从全0到全1,溢出后又为全0)。由于M的值和定时器工作方式有关,因此不同工作方式下定时器的最大定时时间也不一样。例如:若设单片机主脉冲晶体振荡器频率fOSC为12MHz,则最大定时时间为:方式0时 TMmax=2131S=8.192ms方式1时 TMmax=216 1s=65.536ms方式2和3时 TMmax=28 1s=0.256ms 例1、设 方式0工作时,定时时间为1ms,时钟振荡频率为6MHz,解: 将数据代入公式(2)得: (213TC)12/6 S =1
14、ms=1000S TC=213-500=7692化成二进制数为TC=1111 0 0000 01100根据13位定时器/计数器特性,高8位F0H送至TH0低5位0CH送TL0,一般的高三位置“”,可用下列指令实现。MOV TL0,#0CH; 5位送TL0寄存器MOV TH0,#0F0H; 位送T0寄存器 例2若单片机时钟频率fOSC为12MHz,请计算定时2ms所需的定时器初值。 解:由于定时器工作在方式2和方式3下时的最大定时时间只有0.256ms,因此要想获得2ms的定时时间定时器必须工作在方式0或方式1。 若采用方式0,则根据式(2)可得定时器初值为: TC=213-2MS/1s=612
15、9 用计算机附件中的计算器可将6129转换为十六进制数为1830H注意:这不是定时器工作在方式0时的初值,因定时器工作在方式0时是13位,高字节8位,低字节5位,所以还要进行适当的变换,因为1830H 可写成 0001 1000 0011 0000按13位重新组合成00011000001 10000 这组数就可拼成 1100 0001 0001 0000这样就得到定时器工作在方式0时的初值C110H即:TH0应装C1H;TL0应装10H(高三位为0)。 若采取方式1,则有:TC=216-2MS/1s=63536=F830H 即:TH0应装F8H;TL0应装30H。例3、设T1作定时器,以方式1
16、工作,定时时间为10MS;T0作计数器,以方式2工作,外界发生一次事件即溢出。解:T1的时间常数为: (216-TC)2s=10ms TC=EC78H 初始化程序: MOV TMOD,#16H ;T1定时方式1,T0计数方式2,即置TMOD寄存器的内容为00010110 MOV TL0,#0FFH ;T0时间常数送TL0 MOV TH0,#0FFH ;T0时间常数送TH0 MOV TL1,#78H ;T1时间常数(低8位)送TL1 MOV TH1,#0ECH ;T1时间常数(高8位)送TH1 SETB TR0 ;置TR0为1允许T0启动计数SETB TR1 ;置TR1为1允许T1启动计数例4
17、设定时器T0,以方式1工作,试编写一个延时1秒的子程序。解:若主频频率为6MHZ可求得T0的最大定时时间为: TMmax=216 2s=131.072ms我们就用定时器获得100ms的定时时间再加10次循环得到1秒的延时,可算得100ms定时的定时初值:(216-TC)2s=100ms=100000sTC=216-50000=15536TC=3CB0H 程序如下:ORG 0000H MOV TMOD,#01H MOV R7,#10TIME: MOV TL0,#0B0H MOV TH0,#3CH SETB TR1LOOP1:JBC TF0,LOOP2 JMP LOOP1LOOP2:DJNZ R7
18、,TIME RET END7 . 4应用举例例1、广告灯的左移右移方法1: 延时时间使用TIMER0在MODE0下工作1、功能说明 开始时P1.0亮,延时0.2秒后左移至P1.1亮,如此左移7次后至P1.7亮,再延时0.2秒右移至P1.6亮,如此右移7次后至P1.0亮。 延时时间0.2秒,使用TIMER0在MODE0下工作(时钟频率fOSC为12MHz)。2、硬件:见第二章图2-15或图2-163、程序如下:ORG 00H ;起始地址MOV TMOD,#00H ;设定TIMER0工作在MODE0START: CLR C ;C=0MOV A,#0FFH ;ACC=FFH,左移初值MOV R2,#
19、08 ;R2=08,设左移8次LOOP: RLC A ;左移一位MOV P1,A ;输出至P1MOV R3,#100 ;0.2秒ACALL DELAY ;2000微妙DJNZ R2,LOOP ;左移8次MOV R2,#07 ;R2=07,设右移7次LOOP1: RRC A ;右移一位MOV P1,A ;输出至P1MOV R3,#100 ;0.2秒ACALL DELAY ;2000微妙DJNZ R2,LOOP1 ;右移7次JMP START DELAY: SETB TR0 ;启动TIMER0开始计时AGAIN: MOV TL0,#10H ;设定TL0的值MOV TH0,#0C1H ;设定TH0的
20、值LOOP1: JBC TF0,LOOP3 ;TF0是否为1,是则跳至LOOP3,并清TF0JMP LOOP1 ;不是则跳到LOOP1LOOP3: DJNZ R3,AGAIN ;R3是否为0?不是则跳到AGAINCLR TR0 ;是则停止TIMR0计数RET END方法2:延时时间0.2秒,使用TIMER0在MODE1下工作。程序如下:ORG 00H ;起始地址MOV TMOD,#01H ;设定TIMER0工作在MODE1START: CLR C ;C=0MOV A,#0FFH ;ACC=FFH,左移初值MOV R2,#08 ;R2=08,设左移8次LOOP: RLC A ;左移一位MOV P
21、1,A ;输出至P1MOV R3,#20 ;0.2秒ACALL DELAY ;10000微妙DJNZ R2,LOOP ;左移8次MOV R2,#07 ;R2=07,设右移7次LOOP1: RRC A ;右移一位MOV P1,A ;输出至P1MOV R3,#20 ;0.2秒ACALL DELAY ;10000微妙DJNZ R2,LOOP1 ;右移7次JMP START DELAY: SETB TR0 ;启动TIMER0开始计时AGAIN: MOV TL0,#0F0H ;设定TL0的值MOV TH0,#0D8H ;设定TH0的值LOOP1: JBC TF0,LOOP3 ;TF0是否为1,是则;跳至
22、LOOP3,并清楚TF0JMP LOOP1 ;不是则跳到LOOP1LOOP3: DJNZ R3,AGAIN ;R3是否为0?不是;则跳到AGAINCLR TR0 ;是则停止TIMR0计数RET END方法3:延时时间0.2秒,使用TIMER0在MODE2下工作。程序如下:ORG 00H ;起始地址MOV TMOD,#02H ;设定TIMER0工作在MODE2START: CLR C ;C=0MOV A,#0FFH ;ACC=FFH,左移初值MOV R2,#08 ;R2=08,设左移8次LOOP: RLC A ;左移一位MOV P1,A ;输出至P1MOV R4,#04 ;200毫秒A1: MO
23、V R3,#200 ;50毫秒ACALL DELAY ;250微妙DJNZ R4,A1DJNZ R2,LOOP ;左移8次MOV R2,#07 ;R2=07,设右移7次LOOP1: RRC A ;右移一位MOV P1,A ;输出至P1MOV R4,#04 ;200毫秒A2: MOV R3,#200 ;50毫秒ACALL DELAY ;250微妙DJNZ R4,A2DJNZ R2,LOOP1 ;右移7次JMP START DELAY: SETB TR0 ;启动TIMER0开始计时AGAIN: MOV TL0,#6 ;设定TL0的值MOV TH0,#6 ;设定TH0的值LOOP1: JBC TF0
24、,LOOP ;TF0是否为1,是则;跳至LOOP3,并清TF0JMP LOOP1 ;不是则跳到LOOP1LOOP3: DJNZ R3,AGAIN ;R3是否为0?不是则跳到AGAINCLR TR0 ;是则停止TIMR0计数RET END方法4:延时时间0.2秒,使用TIMER0在MODE3下工作。程序如下:ORG 00H ;起始地址MOV TMOD,#03H ;设定TIMER0工作在MODE3START: CLR C ;C=0MOV A,#0FFH ;A=FFHMOV R2,#08 ;R2=08,设左移8次LOOP: RLC A ;左移一位MOV P1,A ;输出至P1MOV R4,#04 ;
25、200毫秒A1: MOV R3,#200 ;50毫秒ACALL DELAY ;250微妙DJNZ R4,A1DJNZ R2,LOOP ;左移8次MOV R2,#07 ;R2=07,设右移7次LOOP1: RRC A ;右移一位MOV P1,A ;输出至P1MOV R4,#04 ;200毫秒A2: MOV R3,#200 ;50毫秒ACALL DELAY ;250微妙DJNZ R4,A2DJNZ R2,LOOP1 ;右移7次JMP START DELAY: SETB TR0 ;启动TIMER0开始计时AGAIN: MOV TL0,#6 ;设定TL0的值LOOP1:JBC TF0,LOOP3 ;T
26、F0是否为1,是则跳至LOOP3,并清楚TF0JMP LOOP1 ;不是则跳到LOOP1LOOP3: DJNZ R3,AGAIN ;R3是否为0?不是则跳到AGAINCLR TR0 ;是则停止TIMR0计数RET END例2、计数器(TIMER0)1、功能说明T0每输入脉冲3次则P1的LED会做BCD码加1的变化,P1.3P1.0为个位(8421码),P1.7P1.4为十位(8421码)。 方法1:TIMER0工作在MODE0计数模式下。2、硬件:见第二章图2-16,只是在8031的14脚(T0)接一个由555组成的方波振荡器,提供计数脉冲。3、程序如下: ORG 0000HSTART:MOV
27、 R2,#00H ;计数指针MOV TMOD,#00000100B ;设定计数工作方式LOOP1:MOV TH0,#0FFH ;设定计数3次MOV TL0,#1DHSETB TR0 ;启动计数器LOOP1:JBC TF0,LOOP3 ;溢出吗?是则跳LOOP3JMP LOOP1 ;不是则往LOOP1LOOP3:MOV A,R2 ;计数指针加1ADD A,#01HDA A ;作BCD码调整MOV R2,A ;存入R2CPL A ;反相以作LO输出MOV P1,A ;输出至P1JMP LOOP1END方法2:TIMER0在MODE1的计数工作方式下。程序如下:ORG 00HSTART:MOV R2
28、,#00H ;计数指针MOV TMOD,#00000101B ;设定计数工作方式LOOP1:MOV TH0,#0FDH ;设定计数3次MOV TL0,#0FFHSETB TR0 ;启动计数器LOOP1:JBC TF0,LOOP3 ;溢出吗?是则跳LOOP3JMP LOOP1 ;不是则往LOOP1LOOP3:MOV A,R2 ;计数指针加1ADD A,#01HDA A ;作BCD码调整MOV R2,A ;存入R2CPL A ;反相以作LO输出MOV P1,A ;输出至P1JMP LOOP1END方法3:TIMER0在MODE2的计数工作方式下。程序如下:ORG 00HSTART: MOV R2,
29、#00H ;计数指针MOV TMOD,#00000110B ;设定计数工作方式LOOP1:MOV TH0,#0FDH ;设定计数3次MOV TL0,#0FDHSETB TR0 ;启动计数器LOOP1:JBC TF0,LOOP3 ;溢出吗?是则跳LOOP3JMP LOOP1 ;不是则往LOOP1LOOP3:MOV A,R2 ;计数指针加1ADD A,#01HDA A ;作BCD码调整MOV R2,A ;存入R2CPL A ;反相以作LO输出MOV P1,A ;输出至P1JMP LOOP1END方法4:TIMER0在MODE3的计数工作方式下。程序如下:ORG 00HSTART:MOV R2,#0
30、0H ;计数指针MOV TMOD,#00000111B ;设定计数工作方式LOOP1:MOV TH0,#0FDH ;设定计数3次SETB TR0 ;启动计数器LOOP1:JBC TF0,LOOP3 ;溢出吗?是则跳LOOP3JMP LOOP1 ;不是则往LOOP1LOOP3:MOV A,R2 ;计数指针加1ADD A,#01HDA A ;作BCD码调整MOV R2,A ;存入R2CPL A ;反相以作LO输出MOV P1,A ;输出至P1JMP LOOP1END应用定时器T0、T1来进行定时或对外部事件计数、利用MCS-51的中断功能,就能使CPU并行地执行多种操作,提高CPU的工作效率。例3
31、:低频信号发生器驱动程序我们设计一个控制程序,使8031的P1口输出8路低频方波脉冲,频率分别为100、50、25、20、10、5、2、1Hz。我们使用定时器T0,产生5ms的定时,若晶振选11.0592MHz,则5ms相当于4608个机器周期,T0应工作于方式1,初值位x为:x=65536-4608=60928。用十六进制数表示则:x=0EE00H。对应于P1.0 P1.7,设立8个计数器,初值分别为1、2、4、5、10、20、50、100,由T0的溢出中断服务程序对它们减“1”计数,当减为零时恢复初值,并使相应的口线改变状态,这样就使P1口输出所要求的方波。下面分别是有关的部分主程序和T0
32、中断处理程序。程序如下: ORG 0START: AJMP MAINORG 0BHPTF0: MOV TH0,#0EEH ;T0中断服务程序CPL P1.0DJNZ 31H,PF01 ;对各路计数器进行计数MOV 31H,#2 ;计数器减为0,恢复计数初值CPL P1.1PF01: DJNZ 32H,PF02 ;输出相反MOV 32H,#4CPL P1.2PF02: DJNZ 33H,PF03MOV 33H,#5CPL P1.3PF03: DJNZ 34H,PF04MOV 34H,#10CPL P1.4PF04: DJNZ 35H,PF05MOV 35H,#20CPL P1.5PF05: DJ
33、NZ 36H,PF06MOV 36H,#50CPL P1.6PF06: DJNZ 37H,PF07MOV 37H,#100CPL P1.7PF07: RETIMAIN: MOV SP,#70 ;主程序:栈指针初始化MOV 31H,#2 ;各路计数器置初值MOV 32H,#4MOV 33H,#5MOV 34H,#10MOV 35H,#20MOV 36H,#50MOV 37H,#100MOV TMOD,#1 ;T0方式1定时MOV TL0,#0 ;初值T0MOV TH0,#0EEHMOV IE,#82H ;允许T0中断SETB TR0 ;允许T0计数HERE: SJMP HERE ;踏步,通常CP
34、U处理其他工作例4:波形展宽程序设P3.4输入低频的窄脉冲信号,要求在P3.4输入发生负跳变时,P1.0输出一个500us的同步脉冲。若晶振频率为6MHz,500us相当于250个机器周期。我们采用如图7-3所示的设计方法。P1.0的初态为高电平,T0选为方式2对外部事件计数,初值为0FFH;这样P3.4输入发生负跳变时,T0产生溢出,程序查询到TF0为1时,T0改变为500us的定时器的工作方式,并使P1.0输出低电平,T0溢出后恢复P1.0高电平,T0又工作于外部事件计数方式。 图7-3 I/O波形和T0方式变换程序如下:START:MOV TMOD,#6MOV TH0,#0FFHMOV
35、TL0,#0FFHSETB TR0LOP1: JBC TF0,PT01 SJMP LOP1PT01: CLR P1.0CLR TR0 ;*1MOV TMOD,#2 ;*2MOV TH0,#11H ;*2MOV TL0,#11H ;*2SETB TR0 ;*1LOP1: JBC TF0,PT02 ;*2SJMP LOP1PT02: SETB P1.0 ;*1CLR TR0SJMP STARTP1.0负脉冲宽度为:(28-17)+112=500us(带*机器周期和为11)例5:简易顺序控制器监控程序在一个简易顺序控制器中,用8031 P1口上的八个继电器来控制一个机械装置的八个机械动作,要求P1口输出如图7-4所示的波形,现在为这个控制器配一个