第7章AT89S51单片机的定时器/计数器17.1定时器/计数器的结构AT89S51定时器/计数器结构见图7-1,定时器/计数器T0由特殊功能寄存器TH0、TL0构成,T1由特殊功能寄存器TH1、TL1构成。2图7-1定时器/计数器结构框图TMOD用于选择定时器/计数器T0、T1的工作模式和工作方式。TCON用于控制T0、T1的启动和停止,同时包含T0、T1状态。计数器起始计数从初值开始。单片机复位时计数器初值为0。7.1.1工作方式控制寄存器TMOD图7-2寄存器TMOD格式(1)GATE—门控位GATE=0,是否计数,由控制位TRx(x=0,1)来控制。GATE=1,是否计数,由外中断引脚INTx*上的电平与运行控制位TRx共同控制。4(2)M1、M0—工作方式选择位M1、M04种编码,对应于4种工作方式的选择,见表7-1。表7-1M1、M0工作方式选择5(3)C/T*—计数器模式和定时器模式选择位C/T*=0,定时器模式,对系统时钟12分频的脉冲进行计数。C/T*=1,计数器模式,计数器对外部输入引脚T0(P3.4)或T1(P3.5)的外部脉冲(负跳变)计数。7.1.2定时器/计数器控制寄存器TCONTCON控制T0、T1的启动和停止,同时包含T0、T1状态。6图7-3TCON格式这里仅介绍高4位功能。(1)TF1、TF0—计数溢出标志位当计数器计数溢出时,该位置“1”。使用查询方式时,此位可供CPU查询,但应注意查询后,用软件及时将该位清“0”。使用中断方式时,作为中断请求标志位,进入中断服务程序后由硬件自动清“0”。(2)TR1、TR0—计数运行控制位TR1位(或TR0)=1,启动计数器计数的必要条件。TR1位(或TR0)=0,停止计数器计数。该位可由软件置“1”或清“0”。7.2定时器/计数器的4种工作方式4种工作方式,分别介绍如下。78图7-5方式1的逻辑结构框图方式1和方式0差别仅仅在于计数器的位数不同7.2.2方式1当M1、M0=01时,工作于方式1,等效电路逻辑结构见图7-5。7.2.1方式07.2.3方式2方式0和方式1最大特点是计数溢出后,计数器为全0。因此在循环定时或循环计数应用时就存在用指令反复装入计数初值的问题,这会影响定时精度,方式2就是为解决此问题而设置的。当M1、M0=10时,工作方式2,等效逻辑结构见图7-6(以T1为例,x=1)。工作方式2为自动恢复初值(初值自动装入)的8位定时器/计数器,TLx(x=0,1)作为常数缓冲器,当TLx计数溢出时,在溢出标志TFx置“1”的同时,还自动将THx中的初值送至TLx,使TLx从初值开始重新计数。定时器/计数器方式2工作过程见图7-7。910图7-6方式2逻辑结构框图11图7-7方式2工作过程方式2可省去用户软件中重装初值的指令执行时间,简化定时初值的计算方法,可相当精确地定时。7.2.4方式3方式3是为增加一个附加的8位定时器/计数器而设置的,从而使AT89S51具有3个定时器/计数器。方式3只适用于T0,T1不能工作在方式3。T1方式3时相当于TR1=0,停止计数(此时T1可作为串口波特率产生器)。1.工作方式3下的T0当TMOD的低2位为11时,T0被选为方式3,各引脚与T0的逻辑关系见图7-8。T0分为两个独立的8位计数器TL0和TH0,TL0使用T0的状态控制位C/T*、GATE、TR0,而TH0被固定为一个8位定时器(不能作为外部计数模式),并使用定时器T1的状态控制位TR1,同时占用定时器T1的中断请求源TF1。12图7-8T0方式3的逻辑结构框图2.T0工作在方式3时T1的各种工作方式一般情况下,当T1用作串口波特率发生器时,T0才工作在方式3。T0方式3时,T1可为方式0、1、2,作为串口波特率发生器,或不需要中断的场合。(1)T1工作在方式0(2)T1工作在方式1当T1的控制字中M1、M0=01时,T1工作在方式1,工作示意见图7-10。14(3)T1工作在方式2当T1控制字中M1、M0=10时,T1为方式2,工作示意如图7-11所示。15图7-10T0方式3时T1为方式1工作示意图图7-11T0方式3时T1为方式2工作示意图(4)T1设置在方式3T0方式3时,再把T1也设置成方式3,此时T1停止计数。7.3对外部输入的计数信号的要求计数器模式时,计数脉冲来自外部输入引脚T0或T1。当输入信号产生负跳变时,计数值增1。每个机器周期S5P2期间,都对外部输入引脚T0或T1进行采样。如在第1个机器周期中采得值为1,而在下一个机器周期中采得的值为0,则在紧跟着的再下一个机器周期S3P1期间,计数器加1。由于确认一次负跳变要花2个机器周期,即24个振荡周期,因此外部输入的计数脉冲的最高频率为系统振荡器频率1/24。16如选用6MHz晶体,允许输入脉冲频率最高为250kHz。如选用12MHz频率晶体,则可输入最高频率500kHz外部脉冲。对外输入信号占空比没有限制,但为确保某一给定电平在变化前能被采样1次,则该电平至少保持1个机器周期。故对外部输入信号要求见图7-12,图中Tcy为机器周期。图7-12对外部计数输入信号的要求187.4定时器/计数器的编程和应用4种工作方式中,方式0与方式1基本相同,只是计数位数不同。方式0为13位,方式1为16位。由于方式0是为兼容MCS-48而设,计数初值计算复杂,所以在实际应用中,一般不用方式0,常采用方式1。7.4.1P1口控制8只LED每0.5s闪亮一次【例7-1】在AT89S51的P1口上接有8只LED,原理电路见图7-13。采用T0方式1的定时中断方式,使P1口外接的8只LED每0.5s闪亮一次。19图7-13方式1定时中断控制LED闪亮(1)设置TMOD寄存器(2)计算定时器T0的计数初值(3)设置IE寄存器(4)启动和停止定时器T020#includereg51.hchari=100;voidmain(){TMOD=0x01;//定时器T0为方式1TH0=0xee;//设置定时器初值TL0=0x00;P1=0x00;//P1口8个LED点亮EA=1;//开总中断ET0=1;//开定时器T0中断TR0=1;//启动定时器T0while(1);//循环等待{;}}21voidtimer0()interrupt1//T0中断程序{TH0=0xee;//重新赋初值TL0=0x00;i--;//循环次数减一if(i=0){P1=~P1;//P1口按位取反i=100;//重置循环次数}}7.4.2计数器的应用【例7-2】如图7-14,T1的采用计数模式,方式1中断,计数输入引脚T1(P3.5)上外接按钮开关,作为计数信号输入。按4次按钮开关后,P1口的8只LED闪烁不停。(1)设置TMOD寄存器(2)计算定时器T1的计数初值(3)设置IE寄存器(4)启动和停止定时器T1。23图7-14由外部计数输入信号控制LED的闪烁#includereg51.hvoidDelay(unsignedinti)//定义延时函数Delay(),i是形式参数,不能赋初值{unsignedintj;for(;i0;i--)//变量i由实际参数传入一个值//因此i不能赋初值for(j=0;j125;j++){;}//空函数}voidmain()//主函数{TMOD=0x50;//设置定时器T1为方式1计数TH1=0xff;//向TH1写入初值的高8位TL1=0xfc;//向TL1写入初值的低8位EA=1;//总中断允许ET1=1;//定时器T1中断允许TR1=1;//启动定时器T1while(1);//无穷循环,等待计数中断}2627voidT1_int(void)interrupt3//T1中断函数{for(;;)//无限循环{P1=0xff;//8位LED全灭Delay(500);//延时500msP1=0;//8位LED全亮Delay(500);//延时500ms}}287.4.3控制P1.0产生周期为2ms的方波【例7-3】假设系统时钟为12MHz,设计电路并编写程序实现从P1.0引脚上输出一个周期为2ms的方波,见图7-15。要在P1.0上产生周期为2ms的方波,定时器应产生1ms的定时中断,定时时间到则在中断服务程序中对P1.0求反。使用定时器T0,方式1定时中断,GATE不起作用。图7-15定时器控制P1.0输出一个周期2ms方波30图7-16定时器控制P1.0输出周期2ms的方波的原理电路31#includereg51.h//头文件reg51.hsbitP1_0=P1^0;//定义特殊功能寄存器P1的位变量P1_0voidmain(void)//主程序{TMOD=0x01;//设置T0为方式1TR0=1;//接通T0while(1)//无限循环{TH0=0xfc;//置T0高8位初值TL0=0x18;//置T0低8位初值do{}while(!TF0);//判TF0是否为1,为1则T0溢出,往下//执行,否则原地循环P1_0=!P1_0;//P1.0状态求反TF0=0;//TF0标志清零}}32仿真时,右键单击虚拟数字示波器,出现下拉菜单,点击“Digitaloscilloscope”选项,就会在数字示波器上显示P1.0引脚输出周期为2ms方波,如图7-17所示。33图7-17虚拟数字示波器显示的2ms的方波波形7.4.4利用T1控制发出1kHz的音频信号【例7-4】利用T1的中断控制P1.7引脚输出频率为1kHz方波音频信号,驱动蜂鸣器发声。系统时钟为12MHz。方波音频信号周期1ms,因此T1的定时中断时间为0.5ms,进入中断服务程序后,对P1.7求反。电路见图7-18。先计算T1初值,系统时钟为12MHz,则方波周期为1µs。1kHz音频信号周期为1ms,要定时计数的脉冲数为a。则T1初值:TH1=(65536−a)/256;TL1=(65536−a)%2563435图7-18控制蜂鸣器发出1kHz的音频信号参考程序如下:#includereg51.h//包含头文件sbitsound=P1^7;//将sound位定义为P1.7脚#definef1(a)(65536-a)/256//定义装入定时器高8位时间常数#definef2(a)(65536-a)%256//定义装入定时器低8位时间常数unsignedinti=500;unsignedintj=0;voidmain(void){EA=1;//开总中断.ET1=1;//允许定时器T1中断.TMOD=0x10;//TMOD=0001000B,使用T1的方式1定时TH1=f1(i);//给定时器T1高8位赋初值.TL1=f2(i);//给定时器T1低8位赋初值.TR1=1;//启动定时器T1while(1)37{//循环等待i=460;while(j2000);j=0;i=360;while(j2000);j=0;}}voidT1(void)interrupt3using0//定时器T1中断函数{TR1=0;//关闭定时器T1sound=~sound;//P1.7输出求反TH1=f1(i);//定时器T1的高8位重新赋初值.TL1=f2(i);//定时器T1的低8位重新赋初值.38j++;TR1=1;//启动定时器T1}7.4.5LED数码管秒表的制作【例7-5】用2位数码管显示计时时间,最小计时单位为“百毫秒”,计时范围0.1~9.9s。当第1次按一下计时功能键时,秒表开始计时并显示;第2次按一下计时功能键时,停止计时,将计时的时间值送到数码管显示;如果计时到9.9s,将重新开始从0计时;第3次按一下计时功能键,秒表清0。再次按一下计时功能键,则重复上述计时过程。本秒表应用定时器模式,计时范围0.1~9.9s。此外还涉及如何编写控制LED数码管显示的程序。本例原理电路见图7-19。39图7-19LED数码管显示的秒表原理电路及仿真40参考程序如下:#includereg51.h//包含51单片机寄存器定义的