51单片机(中断系统)按键控制LED流水灯模式(2)

一、中断系统

中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。

       当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中断源。微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。CPU总是先响应优先级别最高的中断请求。
       当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序),发生了另外一个优先级比它还高的中断源请求。如果CPU能够暂停对原来中断源的服务程序,转而去处理优先级更高的中断请求源,处理完以后,再回到原低级中断服务程序,这样的过程称为中断嵌套。这样的中断系统称为多级中断系统,没有中断嵌套功能的中断系统称为单级中断系统。

二、STC89C52中断资源

        STC89C52系列单片机提供了8个中断请求源,它们分别是:外部中断0(INT0)、定时器0中断、外部中断1(INT1)、定时器1中断、串口(UART)中断、定时器2中断、外部中断2(INT2)、外部中断3(INT3)。所有的中断都具有4个中断优先级。

       用户可以用关总中断允许位(EA/IE.7)或相应中断的允许位来屏蔽所有的中断请求,也可以用打开相应的中断允许位来使CPU响应相应的中断申请:每一个中断源可以用软件独立地控制为开中断或关中断状态;每一个中断的优先级别均可用软件设置。高优先级的中断请求可以打断低优先级的中断,反之,低优先级的中断请求不可以打断高优先级及同优先级的中断。

       当两个相同优先级的中断同时产生时,将由查询次序来决定系统先响应哪个中断。STC89C52系列单片机的各个中断查询次序如下表所示:

以上也是中断服务函数,在初始化中断时也要配置相关的寄存器

 注意:中断的资源和单片机的型号是关联在一 起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等。

                                                                配置中断的触发方式

三、定时器和中断系统

 四、代码

timer0.c标准模板

#include <REGX52.H>


/** 
  * @brief  定时器0初始化,1毫秒@12MHz
  * @param  无
  * @retval 无 
  */
void Timer0Init(void)		//1毫秒@12.000MHz
{
	
			TMOD &= 0xF0;	//设置定时器模式,这里是为了不影响定时器1的配置
			TMOD |= 0x01;	//设置定时器模式
			TL0 = 0x18;		//设置定时初值
			TH0 = 0xFC;		//设置定时初值
			TF0 = 0;		//中断请求标志位 清除TF0标志
			TR0 = 1;		//定时器0开始计时
			ET0=1;			//定时器中断允许控制位
			EA=1;			//总中断允许控制位
			PT0=0;			//定时器中断优先级设置
}

/*定时器中断服务函数模板,这个中断服务函数一般是放在main.c中的
void Timer0_Routine() interrupt 1
{
	    static unsigned int T0Count;
		TL0 = 0x18;		//设置定时初值
	    TH0 = 0xFC;		//设置定时初值
		T0Count++;
		if(T0Count>=1000)
		{
			T0Count=0;
		}
}
*/

 timer0.c解释模板

void Timer0_Init()   //1毫秒@12.000MHz
{
//	   TMOD=0x01;//0000 0001  配置定时器的工作模式寄存器TMOD
//但是用这一行代码,影响配置定时器1,如果要用定时器1的话

		TMOD=TMOD&0xF0;//把TMOD的低四位清零,高四位保持不变
		TMOD=TMOD|0x01;//把TMOD的最低位置1,高四位保持不变
//用这两行代码,可以配置低四位,而不影响高四位

        TH0=64535/256;//给定时器赋初值
		TL0=64535%256;
		TF0=0;     //中断请求标志位 清除TF0标志
		TR0=1;     //定时器0开始计时
		ET0=1;     //定时器中断允许控制位
		EA=1;      //总中断允许控制位
		PT0=0;     //定时器中断优先级设置
}

/*定时器中断服务函数模板,这个中断服务函数一般是放在main.c中的
void Timer0_Routine() interrupt 1
{
	  static unsigned int T0Count;/*放在函数外边是全局变量,放在函数里是局部变量,
	                              因为T0Count是需要计数到1000的,而定时器1ms到后去
	                              执行中断函数,中断函数执行结束后T0Count会被销毁,
	                              无法记录执行次数,因此放在函数体内要加静态变量static
	                              这样T0Count会保留上次的值
	                              */
//		TH0=64535/256;//初始化定时器从64535开始计数,溢出后计数从0开始,因此要重新赋值
//		TL0=64535%256;
		TL0 = 0x18;		//设置定时初值
	    TH0 = 0xFC;		//设置定时初值
		T0Count++;
		if(T0Count>=1000)
		{
			P2_0=~P2_0;
			T0Count=0;
		}
		
}

 用STC-ISP软件生成定时器代码:

 删除AUXR,另外会自动生成TL和TH的值。

main.c

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>

unsigned char KeyNum,LEDMode;

void main()
{
	P2=0xFE;
	Timer0Init();//初始化定时器
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
			if(KeyNum==1)
			{
				LEDMode++;
				if(LEDMode>=2)LEDMode=0;
			}
		}
	}
}


void Timer0_Routine() interrupt 1
{
	  static unsigned int T0Count;/*放在函数外边是全局变量,放在函数里是局部变量,
	                              因为T0Count是需要计数到1000的,而定时器1ms到后去
	                              执行中断函数,中断函数执行结束后T0Count会被销毁,
	                              无法记录执行次数,因此放在函数体内要加静态变量static
	                              这样T0Count会保留上次的值
	                              */
//		TH0=64535/256;//初始化定时器从64535开始计数,溢出后计数从0开始,因此要重新赋值
//		TL0=64535%256;

		TL0 = 0x18;		//设置定时初值
	    TH0 = 0xFC;		//设置定时初值
		T0Count++;
		if(T0Count>=1000)
		{
			T0Count=0;
			if(LEDMode==0)
			{
				P2=_crol_(P2,1);
			}
			if(LEDMode==1)
			{
				P2=_cror_(P2,1);
			}
		}
		
}

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机(中断系统)按键控制LED流水灯模式(2)

发表评论