1、本章介绍的主要内容 定时计数器结构和工作原理 定时计数器的控制寄存器 定时计数器的应用编程,片内有2个16位定时/计数器:定时器0(T0)和定时器1(T1)。 定时或计数功能,应用:控制、延时、计数和检测 定时/计数器实际上是16位加1计数器。T0由2个8位持殊功能寄存器TH0和TL0构成,T1由2个8位持殊功能寄存TH1和TL1构成。 可由软件设置为定时方式或计数方式。 T0和T1受特殊功能寄存器TMOD和TCON控制。,71 8XX51定时/计数器结构和工作原理,1. 定时工作方式, 设置为定时工作方式时,定时器计数的脉冲是由51单片机片内振荡器经12分频后产生的。 每经过一个机器周期定时
2、器(T0或T1)的数值加1直至计数满产生溢出。 如:当8051采用12MHz晶体时,每个机器周期为1s,计5 个机器周期即为5 s,即定时5 s 。,2. 计数工作方式,设置为计数工作方式时,通过引脚T0(P34)和T1(P35)对外部脉冲信号计数。 当输入信号由1至0的下降沿时,定时器的值加1,每个机器周期CPU采样T0和T1的输入电平。若前一周期为高,下一周期为低,则计数器加1。 由于检测一个1至0的跳变需要二个机器周期,故最高计数频率为振荡频率的二十四分之一。 虽然对输入信号的占空比无特殊要求,但为了确保某个电平在变化之前至少被采样一次,要求电平保持时间至少是一个完整的机器周期。,72
3、定时计数器的控制寄存器 两个:定时器控制寄存器TCON(88H)定时器工作模式寄存器TMOD(89H),1. 工作模式寄存器TMOD(89H),TMOD用于控制T0和T1的操作模式。,定时器T0,定时器T1, GATE:门控信号GATE=0,TRx=1时即可启动定时器工作;GATE=1,TRx=1 时INTx=1才可启动定时器工作。 C/T:定时器/计数器选择位C/T=1,为计数器方式;C/T=0,为定时器方式。 M1 M0 工作模式选择位M1M0=00 工作方式0(13位方式)。M1M0=01 工作方式1(16位方式)。M1M0=10 工作方式2(8位自动再装入方式)。M1M0=11 工作方
4、式3(T0为2个8位方式)。,2. 控制寄存器TCON(88H),定时器控制用高4位,低4位用于外部中断。 TF1:T1溢出中断请求标志。 TF0:T0TF1=1,T1有溢出中断请求。TF1=0,T1无溢出中断请求。 TR1:T1运行控制位。 TR0:T0TR1=1,启动T1工作。TR1=0,停止T1工作。,C/T,C/T,7.3 定时器的四种工作方式,THX、TLX(X=1或0)表示TH1 TL1和TH0 TL0。 1.方式 0 13位定时、计数方式,用于计数方式时最大计数值为 213 8192个脉冲用于定时工作时,定时时间为: t(213一T0初值) 时钟周期12 16寄存器(THx和TL
5、x)只用13位,THx占高8位,TLx占低5位, TLx的高3位末用。 当TLx的低5位溢出时向THx进位,而THx溢出时硬件置位TF0,并申请中断。, 定时、计数溢出否可查询TF0是否置位,如果开中断则产生溢出中断。,2 .方式1当TMOD中M1M0=01时,定时计数器工作在方式1。 该模式是一个16位定时计数方式。 寄存器TH0和TL0是以全16位参与操作, 计数方式时最大计数 21665536(个外部脉冲) 用于定时工作方式时,定时时间为: t(216一T0初值) 时钟周期12 16寄存器(THx和TLx) 中THx提供高8位、TLx提供低8位计数初值,3.方式2当TMOD中M1M0=1
6、0时,定时器工作在方式2。方式2是8位的可自动重装载的定时计数方式。 16位的计数器被拆成两个8位,其中TL0用作8位计数器, TH0用以保持计数初值。当TL0计数溢出,置TF0,TH0中的初值自动装入TL0,继续计数,循环重复计数。 用于计数工作方式时,最大计数值为:28256(个外部脉冲)。 用于定时工作方式时,其定时时间为;t(28TH0初值)振荡周期12 这种工作方式可省去用户重装常数的程序,并可产生精确的定时时间,特别适用作串行口波待率发生器。,4.方式3当TMOD中M1M0=11时,定时器工作在方式3。 若将T0设置为模式3,TL0和TH0被分成为两个互相独立的8位计数器TH0和T
7、L0。 TL0可工作为定时或计数方式。占用原T0的各控制位、引脚和中断源。即CT、GATE、TR0、TF0和T0 (P3.4)引脚、INT0(P3.2)引脚。 TH0只可用作定时功能,占用定时器T1的控制位TR1和T1的中断标志位TF1,其启动和关闭仅受TRl的控制。 定时器T1无模式3, 可工作于方式0、1、2,但当T0工作于方式3时T1不能使用中断方式。 只有将T1用做串行口的波特率发生器时,T0才工作在方式3,以便增加一个定时器。,7.4 定时计数器的应用程序设计,7.4.1 定时器的计数初值C的计算和装入由于采用加1计数,因此计数初值应为负值。计数初值(C)的求法如下: 计数方式:计数
8、初值 C=模-X(其中X为要计的脉冲个数) 定时方式:计数初值 C= t/MC补=模t/MC其中t为欲定时时间,MC为机器周期MC=12/fosc当采用12MHZ晶振时,MC=1us;当采用6MHZ晶振时, MC=2us。,方式0( 13位方式):C=(-64H)补=2000H64H=1F9CH1F9CH0001 1111 1001 1100B13位中的高八位1111 1100B装入TH0,13位中的低五位xxx1 1100B装入TL0。MOV TH0,#0FCH;MOV TL0,#1CH;(xxx用“0”填入) 方式1(16位方式):C=(-64H)补=10000H-64H=FF9CHMOV
9、 TH0,#0FFHMOV TL0,#9CH,例 要计100个脉冲的计数初值,方式2(8位自动再装入方式)C=(64H)补=100H64H=9CH初值既要装入TH0,也要装入TL0:MOV TH0,#9CHMOV TL0,#9CH,7.4.2 定时计数器的初始化编程定时计数器的初始化编程步骤: 1)根据定时时间要求或计数要求计算计数器初值; 2)工作方式控制字送TMOD寄存器; 3)送计数初值的高八位和低八位到THX和TLX寄存器中; 4)启动定时(或计数),即将TRX置位。如果工作于中断方式,需要置位EA(中断总开关)及ETX(允许定时/计数器中断)。并编中断服务程序。,例7-1 如图7-2
10、所示, P1中接有八个发光二极管,编程使八个管轮流点亮,每个管亮100ms,设晶振为6MHz。,7.4.3 应用编程举例,分析 利用T1完成100ms的定时,当P1口线输出“1” 时,发光二极管亮,每隔100ms”1”左移一次,采用定时方式1,先计算计数初值:MC= =2s 100ms/2s =50000=C350H (C350H)补 =10000H-C350H=3CB0H* 用汇编语言编程 *,查询方式如下:ORG 0030HMOV A,#01H; 置第一个LED亮 NEXT:MOV P1,A MOV TMOD,#10H ;T1工作于定时方式1MOV TH1,#3CHMOV TL1,#0B0
11、H; 定时100ms SETB TR1 AGAI: JBC TF1,SHI; 100ms到转SHI,并清TF1SJMP AGAI SHI: RL ASJMP NEXT,中断方式ORG 0000H AJMP MAIN ;复位后从0000H开始执行ORG 001BHAJMP IV1 ;转移到IV1ORG 0030H ;主程序 MAIN:MOV A,#01H MOV P1,A ;置第一个LED亮MOV TMOD,#10H ;T1工作于定时方式1MOV TH1,#3CHMOV TL1,#0B0H ;定时100msSETB TR1 ;启动T1工作,SETB EASETB ET1 ;允许T1中断 WAIT
12、:SJMP WAIT ;等待中断 IV1:RL A ;中断服务程序,左移一位 MOV P1,A ;下一个发光二极管亮MOV TH1,#3CHMOV TL1,#0B0H ;重装计数初值RETI ;中断返回 中断子程序直接用A操作,不好!,*用C语言编程*,For(;) TH1=0x3c;TL1=0xb0; /*装载计数初值*/do while(!TF1); /*查询等待TF1置位*/ P1=1; /*定时时间到,下一只LED亮*/TF1=0; /*软件清TF1*/ ,查询方式: #include void main(void) P1=0x01; / *第一只LED亮*/TMOD=0x10 ; /
13、 *定时器1方式1*/TR1=1; /*启动T/C0 */,void main(void)TMOD=0x10; /*T1工作在定时方式1*/P1=0x01; /*第一只LED亮*/TH1=0x3c;TL1=0xb0;/*预置计数初值*/EA=1;ET1=1; /*CPU开中断,允许T1中*/TR1=1; /*启动T1开始定时*/do while(1); /*等待中断*/,中断方式:,#include Timer1( )interrupt 3 using 1 /*T1中断服务程序*/ P1=1; /*下一只LED亮*/TH1=0x3c;TL1=0xb0;/*计数初值重载*/,T0采用方式1, X
14、=216100*103/2=3CB0H, T1采用方式2, 计数初值X =285=FBH 均采用查询方式, 流程图和程序如下:,例7-2 在P1.7端接一个发光二极管LED,要求利用定时控制使LED亮一秒灭一秒周而复始,设fosc=6MHZ。,解:16位定时最大为216*2us=131.072ms,不够。,方法1:T0定时100ms,P1.0每次取反,周期200ms, 输入T1作计数脉冲,T1计5个脉冲正好1s。硬件扩展,ORG 0000H MAIN:CLR P1.7SETB P1.0MOV TMOD,#61HMOV TH1,#0FBHMOV TL1,#0FBHSETB TR1 LOOP1:C
15、PL P1.7,LOOP2:MOV TH0,#3CHMOV TL0,#0B0HSETB TR0;放循环外 LOOP3: JBC TF0,LOOP4SJMP LOOP3 LOOP4:CPL P1.0JBC TF1,LOOP1AJMP LOOP2END,程序中用JBC指令对定时/计数溢出标志位进行检测,当标志位为1时跳转并清标志。,方法2:T0每隔100ms中断一次,利用软件对T0的中断次数进行计数,中断10次即实现了1秒的定时。ORG 000BH ;T0中断服务程序入口 AJMP IP0ORG 0030H ;主程序开始MAIN: CLR P1.7 ;T0定时100msMOV TMOD,#01HM
16、OV TH0,#3CHMOV TL0,#0B0HSETB ET0SETB EA,MOV R4,#0AH;中断10次计数SETB TR0SJMP ;等待中断IP0:DJNZ R4,RET0;用R4计数不好!MOV R4,#0AHCPL P1.7 RET0:MOV TH0,#3CHMOV TL0,#0B0HSETB TR0;可去掉RETI,C语言实现方法1,用中断方式,并用程序计算计数初值: T0定时100ms初值=1001000/2=50000,即-50000。 T1计数5个脉冲工作于方式2,计数初值为-5 #include sbit P1_0=P10;sbit P1_7=P17; timer0
17、() interrupt 1 using 1 /*T0中断服务程序*/ P1_0=!P1_0; /*100ms到P1.0取反*/TH0=-50000/256; /*重载计数初值*/TL0=-50000%256; timer()interrupt 3 using 2 /*T1中断服务*/ P1_!P1_7; /*1s到,灯变状态*/,main() P1_7=0; /*置灯初始灭*/P1_0=; /*保证第一次反向便开始计数TMOD=0x61; /*T0方式定时,T1方式计数*/TH0=-50000/256; TL0=-50000%256; TH1=-5; TL1=-5; *预置计数初值*/ IP
18、=0x08; /*置优先级寄存器*/EA=1;ET0=1; /*ET1=1;开中断*/TR0=1;TR1=1; /*启动定时计数器*/for(;) /*等待中断*/ ,例- 有P3.4引脚(T0)输入一低频信号(其小于0.5kHZ),要求P3.4每发生一次负跳变时, P1.0输出一个500us同步负脉冲,同时P1.1输出一个1ms的同步正脉冲。已知晶振频率为6MHZ。,图7-5,解 按提意,设计方法如图7-5所示。初态P1.1输出高电平(系统复位时实现),P1.1输出低电平,T0选方式计数方式(计一个脉冲,初值为FFH)。当加在P3.4上的外部脉冲负跳变时,T0加1,计数器溢出,程序查询到TF
19、0为1,改变T0为500s定时工作方式,并使P1.0输出,P1.1输出。T0第一次定时500s溢出后,P1.0恢复,T0第二次定时500s溢出后,P1.1恢复,T0恢复外部脉冲计数。设定时500s的初始值为X,则:(256X)2106 = 50010-6解得 X=6,源程序如下: BEGIN:MOV TMOD,#6H ; 设T0为方式外部计数MOV TH0,#0FFH ;计数一个脉冲MOV TL0,#0FFHCLR P1.1 ;P1.1初值为0 SETB TR0 ;启动计数器 DELL: JBC TF0,RESP1 ;检测外跳变信号AJMP DELL RESP1:CLR TR0MOV TMOD
20、,#02H ;重置T0为500s定时,MOV TH0,#06H ;重置定时初值MOV TL0,#06HSETB P1.1 ; P1.1置1CLR P1.0 ; P1.0清0SETB TR0 ; 启动定时计数器 DEL2: JBC TF0, RESP2 ;检测第一次500us到否 AJMP DEL2 RESP: SETB P1.0 ;P1.0恢复1 DEL3: JBC TF0,RESP3;检测第二次500us到否AJMP DEL3 RESP3: CLR P1.1 ; P1.1复0CLR TR0AJMP BEGIN ;思考:如何改为中断方式?,7.4.4 门控位的应用GATEx=1时,TRx=1且
21、INTx=1才启动定时器。利用这个特性可以测量外部输入脉冲宽度。 例7-4 利用T0门控位测试 INT0引脚上出现的正脉冲宽度,设晶振12MHz,将所测得值最高位存入片内71H单元,低位存入70H单元。 解:设外部脉冲由(P3.2)输入,T0工作于定时方式 1(16位计数),GATE设为1。测试时,应在INT0低电平时,设置TR0为1;当INT0变为高电平时,就启动计数;再次变低时,停止计数。此计数值与机器周期的乘积即为被测正脉冲的宽度。因fosc=12MHZ,机器周期为1us,测试过程如下。,源程序如下:MOV TMOD,#09H ; 设T0为方式1MOV TL0,#00H ;设计初值取最大
22、值MOV TH0,#00HMOV R0,#70HJB P3.2, $ ;等P3.2(INT0 )变低SETB TR0 ;启动T0准备工作JNB P3.2, $ ;等待P3.2(INT0 )变高JB P3.2,$ ; 等待P3.2(INT0 )变低CLR TR0 ;停止计数,MOV R0,TL0 ;存放结果INC R0MOV R0,TH0SJMP $读者不难编出C语言程序。这种方案被测脉冲的宽度最大为65535个机器周期。由于靠软件启动和停止计数,有一定的测量误差。其可能的最大误差与指令的执行时间有关。此例中,在读取定时器的计数之前,已把它停止。但在某些情况下,不希望在读计数值时打断定时的过程,
23、由于我们不可能在同一时刻读取THX和TLX的内容。读取一个时恰好另一个产生溢出,在这种情况下,读取的计数值有可能是错的。可以解决错读的方法是:,先读THX后读TLX,若两次读得的THx没有发生变化,则可确定读到的内容是正确的。若前后两次读到的THx有变化,则再重复上述过程,重复读到的内容就应该是正确的了。下面是按此思路编写的程序段,读到的TH0 和TL0放在R1和R0内:RP:MOV A, TH0;MOV R0,TL0;CJNE A,TH0,RP;MOV R1,A,7 6 小 结,定时计数器应用非常广泛,如定时采样、时间测量、产生音响、作脉冲源、制作日历时钟、测量波形的频率和占空比、检测电机转速等。因此应很好掌握。 51系列单片机有两个16位的定时计数器,有四种不同的工作方式,归纳于下表:, 定时和计数实质都是对脉冲的计数,只是被计脉冲的来源不同,定时方式的被计脉冲来源于时钟,计数方式的被计脉冲来源于外部,定时方式的计数初值和被计脉冲周期有关,计数方式的和被计脉冲的个数有关。, 无论定时还是计数,当计满规定的脉冲个数产生溢出(计数初值寄存器回零),置位TFx , 可以通过程序查询,如果允许中断,会产生中断。, 本章应重点掌握定时计数器的应用设计.,