89C51定时/计数器定时/计数器控制寄存器定时/计数器工作方式定时/计数器的应用第6章89C51的定时器/计数器定时/计数器是单片机系统一个重要的部件,其工作方式灵活、编程简单、使用方便,可用来实现定时控制、延时、频率测量、脉宽测量、信号发生、信号检测等。此外,定时/计数器还可作为串行通信中波特率发生器。89C51有两个可编程的定时器/计数器T1、T0。2种工作模式:(1)计数器工作模式(2)定时器工作模式4种工作方式(方式0-方式3)。6.1定时器/计数器的结构TMOD:选择定时器/计数器T0、T1的工作模式和工作方式。TCON:控制T0、T1的启动和停止计数,同时包含了T0、T1的状态。定时器:对片内机器时钟(周期方波)进行计数计数器:对Tx引脚输入的负脉冲进行计数89C51单片机内部有两个定时/计数器T0和T1,其核心是计数器,基本功能是加1。对外部事件脉冲(下降沿)计数,是计数器;对片内机周脉冲计数,是定时器。计数器由二个8位计数器组成。定时时间和计数值可以编程设定,其方法是在计数器内设置一个初值,然后加1计满后溢出。调整计数器初值,可调整从初值到计满溢出的数值,即调整了定时时间和计数值。定时/计数器作为计数器时,外部事件脉冲必须从规定的引脚输入。且外部脉冲的最高频率不能超过时钟频率的1/24。6.1.1工作方式控制寄存器TMOD高4位控制T1低4位控制T0门控位计数/定时方式选择工作方式选择门控位计数/定时方式选择工作方式选择GC/TM1M0GC/TM1M0TMOD用于设定定时/计数器的工作方式低4位用于控制T0,高4位用于控制T1。⑴M1M0——工作方式选择位M1M0工作方式功能00方式013位计数器01方式116位计数器10方式2两个8位计数器,初值自动装入11方式3两个8位计数器,仅适用T0⑵C/T——计数/定时方式选择位C/T=1,计数工作方式,对外部事件脉冲计数,用作计数器。C/T=0,定时工作方式,对片内机周脉冲计数,用作定时器。⑶GATE——门控位GATE=0,运行只受TCON中运行控制位TR0/TR1的控制。GATE=1,运行同时受TR0/TR1和外中断输入信号的双重控制。只有当INT0/INT1=1且TR0/TR1=1,T0/T1才能运行。TMOD字节地址89H,不能位操作,设置TMOD须用字节操作指令。6.1.2定时器/计数器控制寄存器TCONTCON低4位与外中断、有关,已在中断中叙述。高4位与定时/计数器T0、T1有关。⑴TF1:定时/计数器T1溢出标志。⑵TF0:定时/计数器T0溢出标志。⑶TR1:定时/计数器T1运行控制位。TR1=1,T1运行;TR1=0,T1停。⑷TR0:定时/计数器T0运行控制位。TR0=1,T0运行;TR0=0,T0停。TCON的字节地址为88H,每一位有位地址,均可位操作。TCONT1中断标志T1运行标志T0中断标志T0运行标志INT1中断标志INT1触发方式INT0中断标志INT0触发方式位名称TF1TR1TF0TR0IE1IT1IE0IT0位地址8FH8EH8DH8CH8BH8AH89H88HINT0INT16.2定时器/计数器的4种工作方式⒈工作方式013位计数器,由TL0低5位和TH08位组成,TL0低5位计数满时不向TL0第6位进位,而是向TH0进位,13位计满溢出,TF0置“1”。最大计数值213=8192。⒉工作方式116位计数器,最大计数值为216=65536。当fosc=12MHZ,最大定时65536S,而用方式0最大定时时间为8192S.⒊工作方式28位计数器,仅用TL0计数,最大计数值为28=256,计满溢出后,一方面进位TF0,使溢出标志TF0=1;另一方面,使原来装在TH0中的初值装入TL0。优点:定时初值可自动恢复,TH0中存放初值;缺点:计数范围小。适用于需要重复定时,而定时范围不大的应用场合。⒋工作方式3方式3仅适用于T0,T1无方式3。⑴T0方式3在方式3情况下,T0被拆成二个独立的8位计数器TH0、TL0。TL0可以为定时/计数器;TH0只能作为8位定时器。①TL0使用T0原有的控制寄存器资源:TF0,TR0,GATE,C/T,INT0,组成一个8位的定时/计数器;②TH0借用T1的中断溢出标志TF1,运行控制开关TR1,只能对片内机周脉冲计数,组成另一个8位定时器(不能用作计数器)。⑵T0方式3情况下的T1T1由于其TF1、TR1被T0的TH0占用,计数器溢出时,只能将输出信号送至串行口,即用作串行口波特率发生器。6.3计数器模式对输入信号的要求外部计数脉冲的最高频率为系统振荡器频率的1/24,例如选用6MHz频率的晶体,则可输入250KHz的外部脉冲。选用12MHz频率的晶体,则可输入500KHz的外部脉冲。输入信号的高、低电平至少要保持一个机器周期。如图6-12所示,图中Tcy为机器周期。图6-12Tcy6.4定时器/计数器的编程和应用4种工作方式中,方式0与方式1基本相同,由于方式0是为兼容MCS-48而设,初值计算复杂,在实际应用中,一般不用方式0,而采用方式1。其中:N与工作方式有关:方式0时,N=13;方式1时,N=16;方式2、3时,N=8。机周时间与主振频率有关:机周时间=12/foscfosc=12MHZ时,1机周=1S;fosc=6MHZ时,1机周=2S。⒈计算定时/计数初值89C51定时/计数初值计算公式:解:⑴工作方式0:(一个13位的定时或计数器)213–500S/2S=8192-250=7942=1F06H1F06H化成二进制:1F06H=0001111100000110B=0001111100000110B其中:低5位00110前添加3位000送入TL0TL0=00000110B=06H;高8位11111000B送入TH0TH0=11111000B=F8H。【计算定时/计数初值】已知晶振6MHz,要求定时0.5ms,试分别求出T0工作于方式0、方式1、方式2、方式3时的定时初值。⑵工作方式1:(一个16位定时或计数器)T0初值=216-500s/2s=65536–250=65286=FF06HTH0=FFH;TL0=06H。⑶工作方式2:(一个8位计数器(仅作计数器使用))T0初值=28-500s/2s=256-250=6TH0=06H;TL0=06H。⑷工作方式3:(两个8位的计数器或一个8位的定时器)T0方式3时,被拆成两个8位定时器,定时初值可分别计算,计算方法同方式2。两个定时初值一个装入TL0,另一个装入TH0。因此:TH0=06H;TL0=06H。从上例中看到,方式0时计算定时初值比较麻烦,根据公式计算出数值后,还要变换一下,容易出错,不如直接用方式1,且方式0计数范围比方式1小,方式0完全可以用方式1代替,方式0与方式1相比,无任何优点。⒉定时/计数器应用步骤⑴合理选择定时/计数器工作方式⑵计算定时/计数器定时初值(按上述公式计算)⑶编制应用程序①定时/计数器的初始化包括定义TMOD、写入定时初值、设置中断系统、启动定时/计数器运行等。②正确编制定时/计数器中断服务程序注意是否需要重装定时初值,若需要连续反复使用原定时时间,且未工作在方式2,则应在中断服务程序中重装定时初值。6.4.1方式1应用例6-1假设系统时钟频率采用6MHz,要在P1.0上输出一个周期为2ms的方波,如图6-13所示。方波的周期用T0来确定,让T0每隔1ms计数溢出1次(每1ms产生一次中断),CPU响应中断后,在中断服务程序中对P1.0取反。(1)计算初值X设初值为X,则有:(216-X)×2×10-6=1×10-3216-X=500X=65036X化为16进制,即X=FE0CH=1111111000001100B。所以,T0的初值为:TH0=0FEHTL0=0CH(2)初始化程序设计对寄存器IP、IE、TCON、TMOD的相应位进行正确设置,将计数初值送入定时器中。(3)程序设计中断服务程序除产生方波外,还要注意将计数初值重新装入定时器中,为下一次中断作准备。参考程序:ORG0000HRESET:AJMPMAIN;转主程序ORG000BH;T0的中断入口AJMPIT0P;转T0中断处理程序IT0PORG0100HMAIN:MOVSP,#60H;设堆栈指针MOVTMOD,#01H;设置T0为方式1ACALLPT0M0;调用子程序PT0M0HERE:AJMPHERE;自身跳转PT0M0:MOVTL0,#0CH;T0中断服务程序,T0重新置初值MOVTH0,#0FEHSETBTR0;启动T0SETBET0;允许T0中断SETBEA;CPU开中断RETITOP:MOVTL0,#0CH;T0中断服务子程序,T0置初值MOVTH0,#0FEHCPLP1.0;P1.0的状态取反RETI查询方式的参考程序:MOVTMOD,#01H;设置T0为方式1LOOP:SETBTR0;接通T0MOVTH0,#0FEH;T0置初值MOVTL0,#0CHLOOP1:JNBTF0,LOOP1;查询TF0标志CLRTR0;T0溢出,关闭T0CPLP1.0;P1.0的状态求反SJMPLOOPTCONT1中断标志T1运行标志T0中断标志T0运行标志INT1中断标志INT1触发方式INT0中断标志INT0触发方式位名称TF1TR1TF0TR0IE1IT1IE0IT0位地址8FH8EH8DH8CH8BH8AH89H88H例6-2假设系统时钟为6MHz,编写定时器T0产生1秒定时的程序。(1)T0工作方式的确定定时时间较长,采用哪一种工作方式?由各种工作方式的特性,可计算出:方式0最长可定时16.384ms;方式1最长可定时131.072ms;方式2最长可定时512s。选方式1,每隔100ms中断一次,中断10次为1s。(2)计算计数初值因为:(216-X)×2×10-6=10-1所以:X=15536=3CB0H因此:TH0=3CH,TL0=B0H(3)10次计数的实现采用循环程序法。(4)程序设计参考程序:ORG0000HRESET:LJMPMAIN;上电,转主程序入口MAINORG000BH;T0的中断入口LJMPIT0P;转T0中断处理程序IT0PORG1000HMAIN:MOVSP,#60H;设堆栈指针MOVB,#0AH;设循环次数10次MOVTMOD,#01H;设T0工作在方式1MOVTL0,#0B0H;给T0设初值MOVTH0,#3CHSETBTR0;启动T0SETBET0;允许T0中断SETBEA;CPU开放中断HERE:SJMPHERE;等待中断ITOP:MOVTL0,#0B0H;T0中断子程序,重装初值MOVTH0,#3CH;DJNZB,LOOPCLRTR0;1s定时时间到,停止T0工作LOOP:RETI6.4.2方式2的应用方式2是一个可以自动重新装载初值的8位计数器/定时器。这种工作方式可省去程序中重装初值的指令,并可产生相当精确的定时时间。例6-3当T0(P3.4)引脚上发生负跳变时,从P1.0引脚上输出一个周期为1ms的方波,如图6-13所示。(系统时钟为6MHz)(1)工作方式选择T0为方式1计数,初值0FFFFH,即外部计数输入端T0(P3.4)发生一次负跳变时,T0加1且溢出,溢出标志TF0置“1”,发中断请求。在进入T0中断程序后,把TF0标志置“1”,说明T0脚已接收了负跳变信号。T1定义为方式2定时。在T0脚发生一次负跳变后,启动T1每500s产生一次中断,在中断服务程序中对P1.0求反,使P1.0产生周期1ms的方波。(2)计算T1初值设T1的初值为X:则(28-X)×2×10-6=5×10-4X=28-250=6=06H(3)程序设计ORG0000HRESET:LJMPMAIN;复位入口转主程序ORG000BHJMPIT0P;转T0中断服务程序ORG001BHLJMPIT1P;转T1中断服务程序ORG0100HMAIN:MOVSP,#60HACALLPT0M2;调用对