定时器中断

实验:LED灯定时闪烁

/**************************************************************************************
*		              定时器0实验												  *
实现现象:下载程序后D1小灯循环点亮1秒,熄灭1秒。使用单片机内部定时器可以实现准确延时。
注意事项:无。																				  
***************************************************************************************/

#include <reg52.h>

#define u16 unsigned int
#define u8  unsigned char
	
sbit LED = P2^0;	// LED灯

/*******************************************************************************
* 函 数 名         : Timer0Init
* 函数功能		   : 定时器0初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void timer0Init()
{
	/*
	选择为定时器0模式,工作方式1,仅用TR0打开启动。
	TMOD:8位,字节地址89H,各个位分别是:GATE C/T非 M1 M0 GATE C/T非 M1 M0,依次为高4位和低四位
	GATE是门控位,为零时,TR0或TR1为1时,定时计数器就会工作
	CT非:定时/计数模式选择,0为定时模式,1为计数模式
	M1M0:工作方式设置位。00、01、10、11,对应方式0-方式3,一般使用方式1或方式2
	*/
	TMOD |= 0X01;	// 二进制:00000001,表示:GATE=0;CT非=0;M1=01;加上或是为了拉低电平时不受影响
	
	/*
	给定时器赋初值,定时1ms
	上面选择的工作方式1是16位的,单片机采用12MHZ的晶振(机器周期是1us),
	所以初始值=2^16-1000=64536,转成十六进制是:FC18,即高四位是FC,低四位是18,
	所以TH0=0XFC,TL0=0X18,
	*/
	TH0 = 0XFC;	
	TL0 = 0X18;
	
	/*
	打开定时器0中断允许
	ET0:定时/计数器T0中断允许位,为1表示工作
	*/
	ET0 = 1;
	
	/*
	打开总中断
	EA:CPU总中断允许位,为1表示工作
	*/
	EA=1;
	
	/*
	打开定时器
	当GATE为0时,TR0为1,表示打开定时器
	*/
	TR0=1;		
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{
	// 定时器0初始化
	timer0Init();  
	while(1);
}

/*******************************************************************************
* 函 数 名         : void Timer0() interrupt 1
* 函数功能		   : 定时器0中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void timer0() interrupt 1	// 定时器0的中断号为1
{
	static u16 i;	// 用于计数的变量
	
	// 每次中断后,TH0和TL0会置零,所以给定时器赋初值,定时1ms
	TH0 = 0XFC;		
	TL0 = 0X18;
	i++;	// 开始计数
	if(i == 1000)	// 因为一次中断的机器周期是1ms,当计数达到1000时,就是1000ms,即1s
	{
		i = 0;		// 复位
		LED = ~LED;	// 切换LED灯的状态
	}
}

 

第二次看视频写的程序,注释理解不一样:

#include <reg52.h>

#define u16 unsigned int
#define u8 unsigned char
	
// LED灯的D1灯管脚
sbit LED=P2^0;

// 定时器T0初始化函数
void Timer0Init()
{
	/*
	(1)工作方式:TMOD是8位的,高四位用于T1(GATE、C/T非、M1、M0),
	低四位用于T0(GATE、C/T非、M1、M0),它们的使用请参考单片机资料。
	这里设置GATE=0,C/T非=0,M1M0=01(工作方式1,16位定时器),所以低四位是:0001,
	高四位是:0000,所以是0x01
	*/
	TMOD=0x01;
	
	/*
	(2)计算初值:假设定时器定时1ms,即1000us,则需要1001个计数才会溢出,发生中断请求,
	因为定时器0是由TH0和TL0两个寄存器组成,每个寄存器是8位,总共是16位,总数是2^16=65536,
	从0开始计数,所以是0-65535,所以,初值=65535-1000+1=64536,转成十六进制数是:FC18,
	故高四位TH0=0xFC,低四位TL0=0x18
	*/
	TH0=0xFC;
	TL0=0x18;
	
	/*
	(3)中断允许位:如果定时器在数据溢出后需要向单片机CPU发出中断请求,
	还需要开启CPU中断总允许位,即EA=1,同时,需要开启定时器T0的中断允许位ET0,即ET0=1
	*/
	EA=1;
	ET0=1;
	
	/*
	(4)启动定时器工作:由电路图可知,需要将TR0置1,才能让定时器工作
	*/
	TR0=1;
}

// 主函数
void main()
{
	// 定时器初始化
	Timer0Init();
	while(1);
}

// 定时器T0的中断函数
void Timer0() interrupt 1
{
	// 计数变量:用static关键字修饰,表示全局变量
	static u16 i;
	
	/*
	因为定时器选择工作方式1(M1M0=01,表示工作方式1,16位的定时器,没有自动重装功能),
	工作方式2(M1M0=10)由自动重装功能,是8位的定时器,总共有4中工作方式,查资料可知,
	需要把初始值重新写入TH0和TL0中
	*/
	TH0=0xFC;
	TL0=0x18;
	
	/*
	每次中断i都加1表示计数,每次中断时长是1ms,如果想让LED灯每隔1s切换一次状态,
	就需要让i=1000
	*/
	i++;
	if(i==1000)			// 计时达到1s
	{
		i=0;			// 让i复位
		LED=~LED;		// 切换定时器状态
	}
}

 

posted @ 2018-01-31 22:59  半生戎马,共话桑麻、  阅读(909)  评论(0)    收藏  举报
levels of contents