柒:定时/计数器的原理与应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_17017545/article/details/80889138

#定时/计数器的基本概念
定时/计数器,其具有定时和计数的功能。
计数是指对外部脉冲信号进行比较,每来一个脉冲,计数值加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
方式2

**方式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--);
}

猜你喜欢

转载自blog.csdn.net/qq_17017545/article/details/80889138