第七章 定时器与计数器
第七章 定时器与计数器🇨🇳
AT89S52单片机片内集成有3个定时器/计数器T0、T1和T2
7.1定时器/计数器T0与T1的结构😃
一、 AT89S51定时器/计数器结构
-
T0、T1都有定时器和计数器两种工作模式,实质都是对脉冲信号进行计数。
-
计数器模式是对加在T0(P3.4)和T1(P3.5)两个引脚上的外部脉冲进行计数(见上图);
-
定时器模式是对单片机的系统时钟信号经片内12分频后的内部脉冲信号(机器周期)计数,即每个机器周期使寄存器的值加1,属于增1计数器,即每计一个脉冲,计数器增1。
-
定时器可看做是对机器周期的计数器,定时计数频率是振荡频率的1/12。
-
定时时间:可根据对内部脉冲信号的计数值可计算出定时时间。
定时时间 t =计数值N * Tcy -
计数器的起始计数都是从计数器的初值开始。AT89S52单片机复位时计数器的初值为0,也可用指令给计数器装入一个新的初值,从新的初值开始计数。定时器/计数器属于增1计数器。
-
设定计数次数:计数器的计数量程-计数初值
二、 T0、T1的4种工作方式(方式0、1、2和3)
- TMOD--选择定时器/计数器T0、T1的工作模式和工作方式。
- TCON--控制T0、T1的启动和停止计数,同时包含了T0、T1状态。
三、 工作方式控制寄存器TMOD
TMOD用于选择定时器/计数器的工作模式和工作方式,字节地址为89H,不能位寻址
8位分两组,高4位控制T1,低4位控制T0。
-
各位的说明
(1)GATE—门控位
- GATE=0,K=TRx·INTx定时器是否计数,仅由控制位TRx(x = 0,1)来控制运行。
- GATE=1,K=TRx定时器是否运行,由外中断引脚INTx* 上的电平与运行控制位TRx共同控制。
GATE=1时,“与门”的输出信号K由INTx输入电平和TRx位的状态一起决定(即此时K=TRx·INTx),当且仅当TRx=1,INTx=1(高电平)时,计数启动;否则,计数停止。
当INT0引脚为高电平时且TR0置位,TR0=1;启动定时器T0;
当INT1引脚为高电平时且TR1置位,TR1=1;启动定时器T1。
GATE=0时,“或门”输出恒为1,“与门”的输出信号K由TRx决定(即此时K=TRx),定时器不受INTx输入电平的影响,由TRx直接控制定时器的启动和停止。(2)M1、M0—工作方式选择位
M1、M0的4种编码,对应于4种工作方式的选择
(3)C/T* —计数器模式和定时器模式选择位
- C/T*=0, 定时器模式,对系统时钟12分频后的脉冲进行计数。
- C/T*=1, 计数器模式,计数器对外部输入引脚T0(P3.4)或T1(P3.5)的外部脉冲(负跳变)计数。
四、定时器/计数器控制寄存器 TCON Timer Control Register
TCON字节地址88H,可位寻址,位地址为88H~8FH。
-
各位说明
(1)TF1、TF0—计数溢出标志位.
- 当计数器计数溢出时,该位置“1”。
- 使用查询方式时,此位可供CPU查询,但应注意查询后,用软件及时将该位清“0”。
- 使用中断方式时,作为中断请求标志位,进入中断服务程序后由硬件自动清“0”。
(2)TR1、TR0—计数运行控制位
- TR1位(或TR0)=1,为启动定时器/计数器工作的必要条件。
- TR1位(或TR0)=0,停止定时器/计数器工作。
- 该位可由软件置“1”或清“0”。
7.2 定时器/计数器的4种工作方式
- 工作模式:决定定时器或者计数器
- 工作方式:决定计数范围
一。方式0
当M1、M0=00,设置为方式0
-
方式0为13位计数器,由TLx(x = 0,1)的低5位和THx的高8位构成。TLx低5位溢出则向THx进位,THx计数溢出则把TCON中的溢出标志位TFx置“1”。
-
C/T*位控制电子开关决定2种工作模式。
-
GATE位状态决定定时器/计数器运行控制是取决于TRx一个条件,还是取决于TRx和INTx*引脚状态两个条件。
二、方式1
当M1、M0=01时,工作于方式1
- 方式1和方式0差别仅仅在于计数器的位数不同,方式1为16位计数器,由THx高8位和TLx低8位构成(x = 0,1);
- 方式0则为13位计数器,有关控制状态位含义(GATE、C/T* 、TFx、TRx)与方式0相同。
三、方式2
方式0和方式1最大特点是计数溢出后,计数器为全0。因此在循环定时或循环计数应用时就存在用指令反复装入计数初值的问题,这会影响定时精度,方式2就是为解决此问题而设置的。
当M1、M0=10时,工作方式2
- 工作方式2为自动恢复初值(初值自动装入)的8位定时器/计数器;
- TLx(x=0,1)作为常数缓冲器,当TLx计数溢出时,在溢出标志TFx置“1”的同时,还自动将THx中的初值送至TLx,使TLx从初值开始重新计数。
- 方式2适合于用作较精确的脉冲信号发生器
- 方式2可省去用户软件中重装初值的指令执行时间,简化定时初值的计算方法,可相当精确地定时。
四、方式3(T0)
- 方式3是为基本型8051单片机增加一个附加的8位定时器/计数器而设置的,从而使AT89S51具有3个定时器/计数器。
- 方式3只适用于T0,T1不能工作在方式3。
- T1方式3时相当于TR1 = 0,停止计数(此时T1可作为串口波特率产生器)。
-
工作方式3下的T0
TH0被固定作为一个8位定时器(不能作为外部计数模式)并使用定时器T1的状态控制位TR1,同时占用定时器T1的中断请求源TF1。
TL0使用T0的状态控制位C/T* 、GATE、TR0
-
T0工作在方式3时,T1的各种工作方式
- 一般情况下,当T1用作串口波特率发生器时,T0才工作在方式3。
- T0方式3时,T1可为方式0、1、2,作为串口波特率发生器,或不需要中断的场合。
(1)T1工作在方式0
- T1的控制字中M1、M0 = 00时,T1工作在方式0
(2)T1工作在方式1
- 当T1的控制字中M1、M0 = 01时,T1工作在方式1
(3)T1工作在方式2
- 当T1控制字中M1、M0 = 10时,T1为方式2
(4)T1设置在方式3
- T0方式3时,再把T1也设置成方式3,此时T1停止计数。
7.3计数器模式对外部输入的计数信号的要求
-
当定时器/计数器T0与T1工作在计数器模式时,计数脉冲来自外部输入引脚T0或T1。
-
当输入信号产生负跳变时,计数值增1。
-
每个机器周期S5P2期间,都对外部输入引脚T0或T1进行采样。
-
如在第1个机器周期中采得值为1,而在下一个机器周期中采得的值为0,则在紧跟着的再下一个机器周期S3P1期间,计数器加1。
-
由于确认一次负跳变要花2个机器周期,即24个振荡周期,因此外部输入的计数脉冲的最高频率为系统振荡器频率1/24。
也就是 最高频率=系统振荡器频率 / 24
-
如选用6MHz晶体,允许输入脉冲频率最高为250kHz。如选用12MHz频率晶体,则可输入最高频率500kHz外部脉冲。
-
对外输入信号占空比没有限制,但为确保某一给定电平在变化前能被采样1次,则该电平至少保持1个机器周期。
-
故对外部输入信号要求见图7-12,图中Tcy为机器周期。
注意:定时器/计数器的初始化
一、初始化步骤
- 根据要求先给定时器方式寄存器TMOD送一个方式控制字,以设定定时器/计数器的相应工作方式。
- 根据实际需要给定时器/计数器选送定时器初值或计数器初值,以确定需要定时的时间和需要计数的初值。
- 根据需要给中断允许寄存器IE选送中断控制字和给中断优先级寄存器IP选送中断优先级字,以开放相应中断和设定中断优先级(若采用中断方式)。
- 给定时器控制寄存器TCON送命令字,以启动或禁止定时器/计数器的运行。
二、计数器初值的计算
-
定时器/计数器可用软件随时随地启动和关闭,启动时它就自动加1计数,一直计到满,即全为1;若不停止,计数值从全1变为全0,同时将计数溢出,置标志位为1并向CPU发出定时器溢出中断申请。
-
对于各种不同的工作模式,最大的定时时间和计数数值不同。
-
在使用中就会出现两个问题:
(1)要如何产生比定时器最长的定时时间还要短的时间、比计数器最多的计数次数还要少的计数次数;
(2)要如何产生比定时器最长的定时时间还要长的时间、比计数器最多的计数次数还要多的计数次数。 -
如果计数初值设定为C,则计数器从初值C开始作加1计数到计满为全1所需要的计数值设定为D,由此便可得到如下的计算通式:
C = M -D式中,M为计数器量程,该值和计数器工作模式有关。
-
模式0时,M为$2^{13}$;
-
模式1时,M为$2^{16}$;
-
模式2和模式3时,M为$2^{8}$。
三、定时器定时方式的初值计算
-
在定时方式下,计数脉冲由单片机主脉冲经12分频后得到,因此定时器定时时间为:
例题:
7.4 定时器/计数器T1、T0的编程和应用
- 4种工作方式中,方式0与方式1基本相同,只是计数位数不同。方式0为13位,方式1为16位。
- 由于方式0是为兼容MCS-48而设,计数初值计算复杂,所以在实际应用中,一般不用方式0,常采用方式1。
如果定时时间大于最大的可以定时时间,就利用多次的中断
【例7-3】假设系统时钟为12MHz,设计电路并编写程序实现从P1.0引脚上输出一个周期为2ms的方波,见图7-15
基本步骤:
(1)计算T0初值:
设T0的初值为X,有
(216 −X )1 10−6=110−3
即 65536−X=1000
得X=64536,化为16进制数就是0xfc18。将高8位0xfc装入TH0,低8位数0x18装入TL0。
(2)采用查询方式参考程序:
#include <reg51.h> //头文件reg51.h
sbit P1_0=P1^0; //定义特殊功能寄存器P1的位变量P1_0
void main(void) //主程序
{ TMOD=0x01; //设置T0为方式1
TR0=1; //接通启动T0
while(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标志清零
}
}
#include<reg51.h> / /采用中断方式
sbit P1_0=P1^0;
void main(void)
{ TMOD=0x01; /*设置定时器T0为方式1计数*/
P1_0=0;
TH0=0xfc; /*给T0装入初值*/
TL0=0x18; /*给T0装入初值*/
ET0=1; /* 允许T0中断 */
EA=1; /* 总中断开 */
TR0=1 /* 接通T0 计数 * /
do { }while (1); /* 无限循环等待 * /
}
void T0_int(void) interrupt 1 using 1
{ P1_0=! P1_0;
TH0=0xfc;
TL0=0x18;
}
【例4】假设系统时钟为12MHz,编程实现从P1.1引脚上输出一个周期为1s的方波。
基本思想:
- 要在P1.1上产生周期为1s的方波,定时器应产生500ms的周期性定时,定时到则对P1.1求反。
- 由于定时时间较长,用定时器不能直接实现,直接定时时间最长的就是方式1,仅为65ms(系统时钟12MHz)多一点。
- 可以借助P1.0输出计数脉冲,作为计数器(如T1)的输入信号而实现脉冲计数。
实现:
- T0定为10ms定时,每10ms对P1.0求反一次,P1.0输出的脉冲加到定时器T1的计数输入脚P3.5(T1脚),作为计数输入,定时500ms需计数50次。
- T1设为方式2计数,初值X为:$2^{8}$−X=50,则X=206,所以TH1=TL1=206。
- T0设为方式1定时,则方式控制字为0x61。
#include<reg51.h>
sbit P1_0=P1^0;
sbit P1_1=P1^1;
void main(void)
{TMOD=0x61; /*设置定时器T0为方式1定时,T1为方式2计数*/
//0110 0001b
P1_0=0;
TH0=(65536 −10000) /256; /*给T0装初值,方式1 */
TL0=(65536 −10000) %256;
TH1=206; /*给T1装初值*/
TL1=206;
EA=1; /* 总中断开 */
ET0=1; /* 允许T0中断 */
ET1=1; /* 允许T1中断 */
TR0=1;
TR1=1;
while (1);
}
void T0_int(void) interrupt 1
{
TH0=(65536 −10000) /256; /*给T0装初值*/
TL0=(65536 −10000) %256;
P1_0=! P1_0;
}
void T1_int(void) interrupt 3
{P1_1=! P1_1; }; /* P1.1脚产生1s的方波*/ 。
【例5】扩展一个外部中断源
- 方式2可自动重新装载初值。此方式可省去用户程序中重新装初值的指令。
- 当某个定时器/计数器不使用时,可为AT89S51扩展一个负跳沿触发的外部中断源。
- 基本思想:把定时器溢出中断做成外部中断,然后把计数输入信号接到定时器的相应引脚上T0脚(或T1脚),并把定时器被设置为方式2(自动装入常数方式)计数工作模式,计数器TH0、TL0初值均为0FFH,并允许T0中断,总中断开放。
- 当检测到T0脚(或T1脚)引脚电平发生负跳变时,计数器TF0(或TF1)溢出, TF0置“1”,单片机发出中断请求。
扩展一个负跳沿触发的外部中断源,把定时器T0计数输入引脚作为外部中断请求信号的输入端。
#include<reg51.h>
void main( )
{ ………
TMOD=0x06; /*设置定时器T0为方式2计数*/
TH0=0xff; /*给T0装入初值*/
TL0=0xff; /*给T0装入初值*/
ET0=1; /*允许T0中断*/
EA=1; /*总中断开*/
TF0=0; /*T0中断溢出标志位清0*/
TR0=1 /*接通T0 计数* /
while (1) ; /*无限循环等待* /
}
/*以下为定时器T0的中断服务程序*/
void T0_int(void) interrupt 1 using 0
{ 。。。。 } /*外中断处理部分*/
- 本例所述的使用定时器扩展的外中断源只能是负跳沿触发。
- 此外,只有当定时器T0(或T1)不再使用时,才可使用本方法来扩充外部中断源,此时定时器T0本身的功能将不能再使用,除非使用软件来对它进行复用控制。
- 此时,P3.4脚(T0)相当于一个负跳沿触发的外中断请求源输入;对P3.5也可做类似的处理。
测量脉冲宽度——利用GATE门控制
秒表
7.5 定时器/计数器T2的结构与工作方式
- AT89S52与AT89S51单片机相比,新增加了一个16位定时器/计数器T2。
- 与T2相关的特殊功能寄存器共有2个:T2CON和T2MOD。
一、T2的特殊功能寄存器T2CON和T2MOD
- 特殊功能寄存器T2CON
-
TF2:T2计数溢出中断请求标志位。
=1:
=0:
-
EXF2:T2外部中断请求标志位。
当由引脚T2EX(P1.1)上的负跳变引起“捕捉”或“自动重装载”且EXEN2位为1,则置位EXF2标志位,并向CPU发出中断请求。该标志位必须由软件清0。
-
RCLK:串行口接收时钟标志位。
=1:串行通信端使用T2的溢出信号作为串行通信方式1和方式3的接收时钟;
=0:使用T1的溢出信号作为串行通信方式1和方式3的接收时钟。
-
TCLK:串行发送时钟标志位。
=1:串行通信端使用T2的溢出信号作为串行通信方式1和方式3的发送时钟;
=0:串行通信端使用T1的溢出信号作为串行通信方式1和方式3的发送时钟。
-
EXEN2:T2外部采样允许标志位。
=1:如果T2不是正工作在串行口的时钟,则在T2EX引脚(P1.1)上的负跳变将触发“捕捉”或“自动重装载”操作;
=0:在T2EX引脚(P1.1)上的负跳变对T2不起作用。
-
TR2:T2启动/停止控制位。
- 当软件置位TR2时,即TR2=1,则启动T2开始计数,当软件清TR2位时,即TR2=0,则T2停止计数。
-
C/T2* :T2的计数或定时方式选择位.
当设置C/=1时,为对外部事件计数方式;
C/=0时,为定时方式。
-
CP/RL2*:T2捕捉/自动重装载选择位。
- 当设置CP/RL2=1时,如果EXEN2为1,则在T2EX引脚(P1.1)上的负跳变将触发“捕捉”操作;
- 当设置CP/RL2=0时,如果EXEN2为1,则T2计数溢出或T2EX引脚上的负跳变都将引起自动重装载操作;
- 当RCLK位为1或TCLK位为1,CP/RL2标志位不起作用。
- T2计数溢出时,将迫使T2进行自动重装载操作。
-
可以通过软件编程对T2CON 中的相关位进行设置来选择T2 的3种工作方式。
-
T2 的3种工作方式:16位自动重装载(递增或递减计数)、捕捉和波特率发生器,如表7-2所示。
下图很重要:
- T2MOD
-
T2OE:T2输出的启动位。
-
DCEN:置位为1时允许T2增1/减1计数,并由T2EX引脚(P1.1)上的逻辑电平决定是增1还是减1计数。
-
— :保留位。
当单片机复位时,DCEN为0,默认T2为增1计数方式;
当把DCEN置1时,将由T2EX引脚(P1.1)上的逻辑电平决定T2是增1还是减1计数。
#define f1(a) (65536-a)/256
#define f2(a) (65536-a)%256
//a 为初值