51单片机定时器中断原理及应用详解

新版51单片机内部有3个16位可编程的定时器/计数器,即定时器T0,T1,T2。他们既有定时功能又有计数功能,我们可以通过配置与它们相关的特殊功能寄存器可以选择启用定时功能或计数功能;其中需要注意的是,这个定时器系统是单片机内部的一个独立的硬件部分,它与CPU和晶振通过内部某些控制线连接并起作用,CPU一旦设置开启定时器功能后,定时器便在晶振的作用下自动开始计时,当定时器的计数器计满后,会产生中断,即通知CPU该如何处理。

定时器/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时器/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0和T1的启动或停止及设置溢出标志。其结构框图如下:

 加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;另一个是T0或TI引脚输入的外部脉冲源,每来一个脉冲计数器加1,当加到计数器为全1时,再输入一个脉冲就使计数器回0,且计数器的溢出使TCON寄存器中TF0或TF1置1,项CPU发送中断请求(定时器/计数器中断允许时)。如果定时器/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。

因此,由溢出时计数器的值Nt – 计数初值N0 = 加1计数器的计数值N

①设置为定时器模式时,加1计数器是对内部机器周期计数(1个机器周期等于12个振荡周期,计数频率是晶振频率的1/12)。计数值N 乘 机器周期T就是定时时间(机器周器:CPU完成一个基本操作所需时间)。

②设置为计数器模式时,外部事件计数脉冲由T0或T1引脚输入到计数器。在每个机器周期的S5P2期间采样T0或T1电平。当某周期采样到一高电平输入,而下一周期又采样到一低电平时,则计数器加1,更新的计数值在下一机器周期的S3P1期间装入计数器。

知识点:

定时器/计数器工作方式寄存器TMOD,用来确定定时器的工作方式及功能选择,不能位寻址,单片机复位时寄存器全部清零。

TMOD寄存器
位序号 D7 D6 D5 D4 D3 D2 D1 D0
位符号 GATE C/T M1 M0 GATE C/T M1 M0

红色高四位为定时器T1,绿色低四位定时器T0。

GATE——门控制位

GATE = 0,定时器/计数器启动与停止仅受TCON寄存器中TRX(X = 0,1)控制。

GATE = 1,定时器/计数器启动与停止由TOCN寄存器中TRX(X= 0,1)和外部中断引脚(INT0或INT1)上的电平状态来控制。

C/T——定时器模式和计数器模式选择位。

C/T = 1,为计数器模式;C/T = 0,为定时器模式。

M1M0——工作方式选择位

每个定时器/计时器都有4种工作方式,它们有M1M0设定,具体情况如下:

定时器/计数器的4种工作方式
M1 M0 工作方式
0 0 方式0,为13位定时器/计数器
0 1 方式1,为16位定时器/计数器
1 0 方式2,8位初值自动重装的8位定时器/计数器
1 1 方式3,仅适用于T0,分成两个8位计数器,T1停止计数

定时器/计数器控制寄存器TCON,用来控制定时器的启、停以及标志定时器溢出和中断情况,可以位寻址,单片机复位时TCON全部被清零。

TCON寄存器
位序号 D7 D6 D5 D4 D3 D2 D1 D0
位符号 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
位地址 8FH 8EH 8DH 8CH 8BH 8AH 89H 88H

 TF1——定时器1溢出标志位

当定时器1计满溢出时,由硬件使TF1置1,并且申请中断。进入中断服务程序后,由硬件自动清零,需要注意的是,如果使用定时器的中断,那么该位完全不用人为去操作,但是如果使用软件查询的方式的话,当查询到该位置1后,就需要用软件清零。

TR1——定时器1运行控制位

由软件清零关闭定时器1。当GATE = 1,且INT1为高电平时,TR1置1启动定时器1;当GATE = 0时,TR1置1启动定时器1。

TF0——定时器0溢出标志,其功能及操作方法同TF1。

TR0——定时器0运行控制位,其功能及操作方法同TR1。

IE1——外部中断1请求标志、IT1——外部中断1触发方式选择位。

当IT1 = 0时,为电平触发方式,每个机器周期的S5P2采样INT1引脚,若INT1脚为低电平,则置1,否则IE1清零。

当IT1 = 1时,INT1为跳变沿触发方式,当第一个机器周期采样到INT1为低电平时,则IE1置1。IE1 = 1,表示外部中断1正在向CPU申请中断。IE1 = 1,表示外部中断1正在向CPU申请中断。当CPU响应中断,转向中断服务程序时该位由硬件清零。

IE0——外部中断0请求标志,IT0——外部中断0触发方式选择位,该功能操作方法同IE1,IT1。

下面是定时器工作方式1和2的具体工作原理:

方式一
工作原理
采用方式1时,计数位数时16位,由TH0作为高八位,TL0 作为低八位,组成16位加一计数器,在TR0 置1后单片机开始计时,每经过一个机器周期单片机输出一个脉冲使定时器加一,加到16位全为1时会溢出,使TF0 置1,利用此性质可以去执行相应的功能,TF0置1是一个信号。
若 TH0 和 TL0 的初值都为0(即整个定时器的值为0000000000000000),当16位全为1时,单片机一共输出了65535个脉冲,再来一个脉冲计数器就溢出,时间经过了65536*12/12M秒钟即为65.536ms。

初值的设定
那么问题来了,我们想要利用的时间都是1s,2s这种,而不是65.536ms,如果能让开始计时到TF0 置1这个时间变成50ms这种,就能够通过几次计数溢出达到计时1s钟的目的,这就到了初值的计算。
由之前的分析可知,单次计时最长为65.536ms,以单次定时50ms(0.05s)为例,需要20次可以定时1s钟。假设开始计时时16位定时器的初值为x,由于单片机定时固定到达65536溢出,那么(65536-x)*12/12M = 0.05,可计算得到x = 15536。化为16进制为0x3cb0。那么TH0 = 0x3c, TL0 = 0xb0;把15536/256 = 60(0x3c)装入TH0中,把15536%256 = 176(0xb0)装入TL0中。

代码实现

定时1s钟的代码如下:

#include<reg52.h>

void main()
{
	unsigned char cnt = 0;
	TMOD = 0x01;  //设置定时器为工作方式1
	TH0 = 0x3c;
	TL0 = 0xb0; //设置初值
	TR0 = 1; //打开定时器开关,开始定时
	while(1)
	{
		if(TF0 == 1)
		{
			TF0 = 0;
			TH0 = 0x3c;
			TL0 = 0xb0;
		 //单次计时完成后,TH0 与TL0 的值均为11111111,所以需要对他们重新赋初值
		 	cnt++;
		 	if(cnt == 20)
		 	{
		 		cnt = 0;
		 		//此处填写定时完成时要执行的功能	
		 	}
		}
	}
}

方式二
工作原理
方式2是自动重装初值的8位计数方式,在本质上是与方式1一样的。在工作方式2中,TH0 只起到为TL0 重装初值的作用,并不参与计数。当TL0 计数到全为1时再有一个脉冲就会触发溢出,TL0 的溢出不仅使TF0 置1,TF0置1是一个信号 ,而且将TH0内容重新装入TL0 ,TH0 内容由代码设置,重装时值不变,然后进行新一轮的定时 ,这就是所谓方式2自动重装初值。

初值的设定
方式2的初值的计算方式和方式1相同,与方式1不同的是:由于方式2只有TL0 计数,最多可以记256个脉冲(8位从全0编为全1),单次定时最长也就只有0.256ms(方式1为65.536ms)
依然以定时1s钟为例,单次定时时间为0.2ms,设初值为x,(256-x)*12/12M = 0.2**10-3(0.2乘10的-3次方,由于格式问题只能打两个星号……),解得x = 56,化为十六进制为0x38,则TH0 和TL0 的初值均为0x38;
代码实现

#include<reg52.h>

void main()
{
	unsigned int cnt = 0;
	TMOD = 0x02;
	TH0 = 0x38;
  	TL0 = 0x38;
  	TR0 = 1;
  	if(TF0 == 1)
  	{
  		TF0 = 0;
  		//TH0 = 0x38;
  		//TL0 = 0x38; 这两处由于是自动重装初值,所以单次定时结束后不需要再赋值
  		cnt++;
  		if(cnt == 5000)
  		{
  			cnt = 0;//单次定时0.2ms,5000次后定时1s
  			//此处填写定时完成时要执行的功能
  		}
  	}
}

中断服务程序格式

void T1_time_() interrupt 中断号 
{
    中断服务程序内容
    
}

中断函数不能返回任何值,所以最前面用void;后面紧跟函数名,名字可以随便起,但不要与C语言中的关键字相同;中断函数不带任何参数,所以后面的小括号内为空;中断号是指单片机中几个中断源的序号,这个必须写对。

例子:

void T1_time() interrupt 3
{
    TH1 = (65536-10000)/256;
    TL1 = (65536-10000)%256
}

 上面的代码是一个定时器1的中断服务程序,定时器1的中断序号为3,因此我们要写成interrupt 3,服务程序内容是给两个寄存器装入初值。

写代码总结:

在写单片机的定时器程序时,在程序开始处需要对定时器及中断寄存器做初始化配置,通常定时器初始化过程如下:

①对TMOD赋值,以确定T0和T1的工作方式。

②计算初值,并将初值写入TH0、TL0或TH1、TH1。

③写中断方式,则对IE(中断允许寄存器)赋值,开放中断,必要时,还得写中断优先级(IP)。

④使TR0或TR1置位,启动定时器/计数器定时或计数

如果使用软件查询方式的话

⑤TF0 = 0;  //清除TF0标志

    TF1= 0; //清楚TF1标志

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机定时器中断原理及应用详解

发表评论