定时/计数器的基本概念
定时/计数器,其具有定时和计数的功能。
计数是指对外部脉冲信号进行比较,每来一个脉冲,计数值加1;当产生的信号脉冲很有规律时,比如1秒钟来一个,那么计数多少个脉冲就知道过了多少秒,从而计数功能可以演化为定时功能。
定时功能需要用到某个基准时钟,通过对基准时钟的计数来完成定时功能。
定时/计数器的种类比较多,但一般可归为两类:
(1)专用的定时/计数器器件(如8253);
(2)处理器中集成定时器/计数器(如8051单片机自带2个16位定时/计数器)。这些定时器一般都有一个输入时钟,即基准时钟。
定时/计数器有如下一些用途:
(1)产生所需频率的脉冲。如产生频率1000,占空比1:1的脉冲波。
(2)在累加计数中的应用。计数器可在一段时间内记录信号A经整形后的脉冲个数。
(3)在频率测量中的应用。通过测量脉冲宽度或在一定时间内测量脉冲的个数,从而推算出脉冲的频率。
(4)定时/计数器在计时中的应用。定时/计数器可对时钟信号,如秒信号进行计数,也可用来倒计时,秒表计,时间循环等。
51单片机的定时/计数器
8051单片机内部有2个16位的定时/计数器:T1和T0。
T0定时/计数器详解: 寄存器位C/T控制开关,往上是振荡器,即CPU晶振产生的脉冲,往下是P3.4的引脚,即从外部得到的脉冲信号。进来之后首先送到TL0寄存器中,当TL0寄存器计数满了之后,就会进位到TH0寄存器,当TH0寄存器计数满了之后,就会产生溢出信号,TCON寄存器就会设置一个相应的标志,标志会引发CPU的中断,即51单片机的内核处理单元处理。整个定时器是受到TMOD和TCON这两个寄存器的控制,分别控制工作模式与工作状态。
1、计数功能与定时功能
计数功能就是对外部脉冲进行计数;
计时就是针对内部振荡器,一般12MHz,除以12 ,就是1MHz,相当于一个脉冲就是1us,数多少个脉冲就知道多少us,就是定时功能;
2、T0相关寄存器4个
寄存器描述
6个相关的寄存器:TMOD、TCON、TH0、TL0、TH1、TL1
其中TMOD用于控制和确定各定时/计数器的功能和工作方式,TCON用于控制各定时/计数器的启动和停止计数,同事 包含定时/计数器的状态,TH0、TL0用于T0的计数,TH1、TL1用于T1的计数。系统复位时,这些寄存器的所有为都被清零。
#TMOD方式寄存器描述
![]() | ![]() |
C/T:选择计数器或定时器功能,C/T=1位外部脉冲计数器功能,C/T=0为内部脉冲计数器功能(可做定时器)
GATE:选通控制,GATE=0,由软件控制TR0或TR1位启动定时器:GATE=1,由外部中断引脚INT0(P3.2)和INT1(P3.3)输入电平分别控制T0和T1的运行。
方式1
方式0和方式1工作过程差不多,只不过方式0为13位计数方式,最大计数值只能达到213=8192;而方式1为16位计数方式,最大计数值为216=65536。
当工作在计数方式时,最大计数值为2^16=65536。
当为定时工作方式时,定时时间计算公式为:
T=(216-计数初值)×晶振周期×12=(216-计数初值)×12÷晶振频率
假设晶振频率为12MHz,则方式1下最大定时时间T=(2^16-0)×12÷12MHz=65536x1us=65.536ms。
方式2
方式2为8位计数方式,最大计数值为2^8,能够自动重装计数值。
方式2特别适合于把定时/计数器用作串口波特率发生器。
定时时间T=(2^8-计数初值)×晶振周期×12 =(2^8-计数初值)×12÷晶振频率。
|
|
---|---|
![]() | ![]() |
方式1详解: C/T开关控制脉冲的来源,不管哪种脉冲,都会送到K往后计数,其中K的状态受下方逻辑控制。当GATE=0,A处输出1,此时B处的状态只受TR0控制,当TR0=1,K处开关闭合,当TR0=0,K处开关断开,即只通过TR0(软件控制位)来控制定时器。当GATE=1,A处输出值受INT0引脚控制,当TR0=1,此时K状态只受INT0控制,当INT0=1,K处开关闭合,当INT0=0,K处开关断开,即只通过引脚的电平来控制定时器。开关闭合后,开始计数,TL0计数满进位到TH0,TH0计数满进位到TF0(中断标志),即产生中断给了51。
方式2详解: 方式2与方式1的前面大部分原理相同,不同的是8位计数方式,TL0计数满直接进位给TF0产生中断,同时通过选通控制将TH0(已设置好)的值覆盖到TH0(自动重装计数值),重新计数。
TCON寄存器描述
其中高4位控制定时/计数器T0和T1的运行,低4位控制外部中断INT1和INT0的运行。
TF1: T1计数溢出标志位,计数寄存器产生溢出时由硬件自动置位,置位后向CPU申请中断,中断响应后硬件自动复位,若采用程序查询方式,必须软件清除该位。
TR1: T1运行控制位,由软件置位和复位。当GATE(TMOD.7)为0时,由软件设置为“1”时立即启动T1计数寄存器开始计数,清除为“0”时立即停止T1计数器寄存器计数。当GATE为1时,置位TR1为“1”时还必须INT1输入为高电平时,才启动T1计数,清除为“0”时或INT1输入为低电平时均可停止T1计数。
TF0: 定时器T0溢出标志位,其含义与TF1类似。
TR0: 定时器T0的运行控制位,其含义与TR1类似。
#使用步骤
1、定时/计数功能的确定,从而确定C/T位的值;以及T0、T1的选用。
2、计数值的确定。 如果选择为定时功能,则需要计算计数值,公式如下:
(注:一个机器周期等于12个时钟周期,时钟周期是晶振振荡频率的倒数)
计数值 = 定时时间/机器周期 = 定时时间×12/晶振频率。比如单片机系统的晶振频率为12MHz,现需要定时1ms,则计数值 = 1ms × 12/12MHz = 1000。
3、确定定时/计数器的工作方式,一般选用方式1和方式2,当需要计数值比较大时(计数值>256),选用方式1工作,此时最大计数范围为2^16。
4、计数初值的确定,即THn和TLn的确定。因为51单片机的定时/计数器是采用计满溢出的,所以:计数初值=(计数最大值-计数值),从而确定计数初值。比如计数值为1000,选用方式2(16位寄存器),则:计数初值 = 2^16-1000 = 64536 = 0xFC18,所以THn = 0xFC,TLn = 0x18。
5、溢出标志位TFn(n=0或1)清0。
6、运行控制位TRn置1,定时/计数器开始计数。
实验
汇编代码
******************************************************************/
* 【课程8】 ****定时/计数器的应用***********
* 【说 明】 ****使用T0做脉冲信号发生器,(查询的方法)
* 【描 述】 ****在P1.7这个引脚上产生500Hz的方波
******************************************************************/
ORG 0000H
MAIN: SETB P1.7
MOV TMOD,#01H ;设置T0工作在定时功能,方式1
MOV TH0,#0FEH ;设置计数初值
MOV TL0,#0cH
CLR TF0 ;清除TF0位
SETB TR0 ;启动T0
Loop: JNB TF0,$ ;查询TF0位是否置位
CLR TF0 ;清除溢出标志位TF0
CPL P1.7 ;翻转P1.7引脚电平
MOV TH0,#0FEH ;重新给T0赋初值
MOV TL0,#0cH
JMP Loop
END
C代码
******************************************************************/
* 【课程8】 ****定时/计数器的应用***********
* 【说 明】 ****使用T0做脉冲信号发生器,(查询的方法)
* 【描 述】 ****在P1.7这个引脚上产生500Hz的方波
******************************************************************/
#include<reg51.h> //51头文件,
//---------常用的两个宏定义--------------
#define uint8 unsigned char
#define uint16 unsigned int
sbit Put=P1^7; //波形输出端口
void main()
{
TMOD=0x01; //T0工作在方式1下,16位定时功能
TH0=0xfc; //装计数初值,定时1ms
TL0=0x18;
TF0=0; //清除TF0标志位
TR0=1; //启动T0
while(1)
{
if(TF0==1) //判断T0溢出标志位是否为1
{
Put=~Put; //输出端口取反
TF0=0;
TH0=0xfc; //重装计数初值
TL0=0x18;
}
}
}
#TIMER0控制流水灯
C代码
******************************************************************/
* 【课程8】 ****定时/计数器的应用***********
* 【说 明】 ****使用T0定时
* 【描 述】 ****使用T0精确定时让LED循环亮
******************************************************************/
#include<reg51.h> //51头文件,
#include<intrins.h>
//---------常用的两个宏定义--------------
#define uint8 unsigned char
#define uint16 unsigned int
//------------函数的声明-----------------
void DelayMS(uint16 dly);
void Led_Disp(void);
void main()
{
P1=0xfe;
TMOD=01;
TH0=-50000/256;
TL0=-50000%256;
EA=1;
ET0=1;
TR0=1;
while(1);
}
/**************中断服务函数*******************/
void T0_time() interrupt 1
{
uint16 i;
TH0=-50000/256;
TL0=-50000%256;
i++;
if(i==10)
{
Led_Disp();
i=0;
}
}
/********************************************************
** 名称 :void Led_Disp(void)
** 功能 :LED灯循环显示
** 入口参数 :无
** 出口参数 :无
*********************************************************/
void Led_Disp(void)
{
uint16 temp;
DelayMS(100);
temp=P1;
temp=_crol_(temp,1);
P1=temp;
}
/********************************************************
** 名称 :void DelayMS(uint16 dly)
** 功能 :毫秒级延时(24M的晶振)
** 入口参数 :dly 用户的延时参数
** 出口参数 :无
*********************************************************/
void DelayMS(uint16 dly)
{
uint16 x,y;
for(x=dly;x>0;x--)
for(y=124;y>0;y--); //12M
// for(y=247;y>0;y--);
}