[51 单片机] --定时器中断

1,前置知识

振荡周期: 为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)。

状态周期: 2 个振荡周期为 1 个状态周期,用 S 表示。振荡周期又称 S 周期或时钟周期。

机器周期:1 个机器周期含 6 个状态周期,12 个振荡周期

指令周期:完成 1 条指令所占用的全部时间,它以机器周期为单位。一般1~4个机械周期

如:

        外接晶振为 12MHz 时,51 单片机相关周期的具体值为:

        振荡周期 = 1/12us;
        状态周期 = 1/6us;
        机器周期 = 1us;
        指令周期 = 1~4us;

 2,51单片机定时器

 ①:51单片机有两组基本的定时器,因为既可以定时,又可以计数,故称之 为【定时器/计数器】

②:定时器/计数器和单片机的 CPU 是相互独立的。定时器/计数器工作的过程 是自动完成的,不需要 CPU 的参与。

③:5 1 单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信 号对寄存器中的数据加 1。
---> 定时/计数器的实质是加 1 计数器(16 位),由高 8 位和低 8 位两 个寄存器 THx 和 TLx 组成。

 内部结构图:

 上图描述了两个定时器T0/T1,计数脉冲是由机器周期脉冲,定时器颞部由两个寄存器为TH0,TL0分别为8bit数据,即定时器初值。

TMOD定义了定时器工作方式,高4位为T1,低4位为T0.

TCON 寄存器为中断请求标志控制寄存器,TF0位中断溢出标志,TR0 = 1为开启定时器0.

 GATE 门控位:控制定时器是否受外部中断源信号影响。

        GATE为0时,不受外部中断控制,启动定时器可以通过TR0 = 1/0 和TR1 = 1/0,控制定时器启动。

        GATE = 1时,不仅需要TR0 =1/0,TR1 = 1/0控制定时器启动,还需要外部中断控制引脚INT0、INT1 位1,才能启动定时器工作。

C/T 位: 表示定时/计数模式选择位。C/T =0 为定时模式;C/T =1 为计数模式

M1M0:工作方式设置位。定时/计数器有四种工作方式。

 定时器一般使用工作方式1,工作方式二一部用于串口定时。

 前一章节提到过这个定时器,低4位为外部中断控制位和中断溢出位,这个高4位为定时器中断控制位和溢出位。所以启动定时器需要去设置TR0、TR1.

注:T1 计数溢出时由硬件自动置 TF1 为 1。CPU 响应中断后 TF1 由硬件自动清 0

注重介绍方式1工作原理:

  

 从右到左看,TMOD寄存器GATE经过一个非门,一级INT0外部中断0的引脚绑定到一个>=1的逻辑门上,我们知道不管Gate位取值多少,要启动定时器需要TR0 = 1,从图中的&门可以看出,如果Gate位为1,则取决于INT0引脚的值是否为1,如果Gate位为0,则与INT0引脚无关,这就是门控位所决定的事。

在看到TMOD中的C/T 位,C/T = 0时为连接到机器周期,C/T = 1时,连接到T0引脚(即单片机P32上)。

使用当中间开关闭合时,定时器就工作了。

所以如何让定时器0工作啦?代码如何操作寄存器。

TMOD |= 0x01 // 让定时器工作在方式1,同时c/t = 0, gate = 0(关闭外部中断影响);

TH0 = 0xFF; // 定时器初值高位

TL0 = 0xAA; // 定时器初值低位

ET0 = 1;  //开启Time0中断允许位

EA = 1; // 开启cpu中断使能

TR0 = 1;//启动定时器

 3,定时器初值的计算

因为我们让定时器的C/T = 0,即定时信号来自于机器周期,我们知道机器周期等于12 个震荡周期。所以我们如何计算定时的初值那?

我的51单片机所以得外部晶振是11.0592Mhz的,

一个机器周期 时间:T = (12 *1)/ ( 11.0592 * 10^(6) ) =  1.08507 x 10^(-6)s = 1.08507us

由于TH0,TL0最大为16位即,最大值位0xFFFF = 65535,在来一个脉冲就溢出了。如果我现在要实现定时1ms,这个初值怎么计算:

        1000 / 1.08507 = 922 个脉冲 ,即定时器需要计数922个脉冲,即使用65536 - 922 = 64614,这个值就为计数器初值:0xFC66.

4,定时器代码实现

实现两定时器每隔1s,1.5s亮灭LED0,LED1 (注意中断号)

#include <reg52.h>

  // 1.08507us -->一个机器周期 (12 / 11.0592 us)
  // 从初始值加1,直到加到最大值产生time中断
typedef unsigned char u8;
typedef unsigned int u16;

sbit LED1 = P2^0;
sbit LED2 = P2^1;

void init_time0()
{
	TMOD |= 0x01; // 选择定时器0,工作方式1
	TH0 = 0xFC;	  //初始time0高位
	TL0 = 0x66; //初始time0低位
	ET0 = 1;	// 打开定时器0中断允许
	EA = 1;		// 打开系统总中断使能
	TR0 = 1;    // 	打开定时器	 	
}

void time0_run() interrupt 1
{
	static u16 i = 0;
	
	//重新设置中断
	TH0 = 0xFC;	  //初始time0高位
	TL0 = 0x66; //初始time0低位
					  // 1s
	i++;

	if(i == 1000)
	{
		i=0;
		LED1 = !LED1;	
	}
}

void init_time1()
{
	TMOD |= 0x10; // 选择定时器1,工作方式1
	TH1 = 0xFC;	  //初始time1高位
	TL1 = 0x66; //初始time1低位
	ET1 = 1;	// 打开定时器1中断允许
	EA = 1;		// 打开系统总中断使能
	TR1 = 1;    // 	打开定时器	 	
}

void time1_run() interrupt 3
{
	static u16 i = 0;
	
	//重新设置中断
	TH1 = 0xFA;	  //初始time0高位
	TL1 = 0x9A; //初始time0低位
						   // 1.5s
	i++;

	if(i == 1000)
	{
		i=0;
		LED2 = !LED2;	
	}
}

void main()
{
	init_time0();
	init_time1();
	while(1);
}

 5,总结

        定时器操作较为复杂,需要着重理解方式1的工作原理,才能对代码操作的每个寄存器弄明白。其次这里并没有介绍将C/T = 1(计数模式),后期遇到再补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值