14:中断

中断

  • 1、中断的引入
  • 2、使用单片机外部中断来处理按键
    • 2.1、外部中断
    • 2.2、参考数据手册中示例代码写程序
      • 2.2.1、外部中断0的测试程序
      • 2.2.2、完整程序

1、中断的引入

任务:独立数码管循环显示0-9,同时按键控制LED1亮灭。

代码如下:

#include 

sbit K1 = P1^0;
sbit LED1 = P2^0;

void delay(void)//延迟函数
{
	unsigned char a,b;
	for(a=200 ;a>0 ;a--)
	   for(b=200 ;b>0 ;b--)
	         ;
}
void main(void)
{
	unsigned char val[10]= {0xc0,0xf9,0xa4,0xb0,0x99,
  0x92,0x82,0xf8,0x80,0x90};//0~9的数码表
	while(1)
	{
			unsigned char i;
			for(i=0 ;i<=9 ;++i)
			{
				P0 = val[i];//数码管不断循环显示0到9
					delay();	
			}
			
			if(K1 == 0) //K1按下时
				 LED1 = 1;//LED1亮
			else
				 LED1 = 0;
  }

}

分析能否实现:实践证明可以实现功能,但是按键监测控制LED这边非常不灵敏。
分析原因:单片机在不断循环执行此代码,当执行到下列这段代码时,

         unsigned char i;
		for(i=0 ;i<=9 ;++i)
		{
			P0 = val[i];//数码管不断循环显示0到9
				delay();	
		}

所消耗的时间是很长的,假如执行一句代码的时间为1,则执行此段代码的时间是10次循环时间*延迟函数的时间,大约为10x200x200。

而当执行下列这段代码时:

       if(K1 == 0) //K1按下时
			 LED1 = 1;//LED1亮
		else
			 LED1 = 0;

只需要大约4的时间,所以时间非常短的。

按键监测控制LED这边非常不灵敏:当我们按下K1时,可能CPU还在执行上面循环代码,而没有执行下列判断代码,所以导致LED不能马上亮灭。所以我们要引入中断。

中断的思路
(1)“主线任务”为常规任务(执行时间长),默认运行
(2)中断发生后CPU暂停主线任务转去处理中断任务,完成后再回来接着执行主线任务

中断的意义
(1)中断处理能力让CPU可以全力处理主线任务而不用担心会错过中断任务(举例:看电影和收快递)
(2)中断式比轮询式更适合处理异步事件,效率更高。
(3)中断中处理的事件的特点是:无法预料、处理时间短、响应要求急。

2、使用单片机外部中断来处理按键

2.1、外部中断

(1)何为外部中断。中断源来自于单片机外部就叫外部中断,51支持4个外部中断。分别对应4个引脚。每一个外部中断都对应一个特定的单片机IO引脚(譬如INT0对应P3.2,这个是单片机在设计时候定好的,是无法改变的)。我们软件只需要对P3.2做一些相关配置,P3.2就可以响应外部的中断事件。当硬件产生了一个外部中断时CPU就会收到一个中断信号,从而转去执行外部中断对应的处理程序(这个处理程序也是我们软件需要去编写提供的)。

在这里插入图片描述14:中断_第1张图片

2.2、参考数据手册中示例代码写程序

2.2.1、外部中断0的测试程序

14:中断_第2张图片IT0,EX0,EA其实都是在51头文件里面用sbit定义好了的
14:中断_第3张图片

IT0这一位用来设置中断的触发模式:下降沿触发(Falling)或者低电平触发(low level)。
EX0这一位是INT0的开关。如果EX0等于0则外部中断在单片机内部被关闭,此时CPU无法收到INT0的中断信息所以不会处理INT0;如果需要使用INT0就一定要设置为1。
EA是全局的中断开关。EA如果关掉则整个CPU不能响应中断,所有中断都被关了。光EA打开也不一定能响应中断,还得具体的中断开关打开才行。
exint函数里面执行的时中断程序。

2.2.2、完整程序

#include 

sbit K1 = P3^2;//K1接线到中断0的引脚
sbit LED1 = P2^0;

void delay(void)//延迟函数
{
	unsigned char a,b;
	for(a=200 ;a>0 ;a--)
	   for(b=200 ;b>0 ;b--)
	         ;
}

void delay10ms(void)  //消抖的延迟函数
{
    unsigned char a,b,c;
    for(c=5;c>0;c--)
        for(b=4;b>0;b--)
            for(a=248;a>0;a--);
}
/***********中断函数执行次线任务********/
void ZongDuang() interrupt 0
{
	    if(LED1 == 0)//判断LED灯灭着的
			{
				if(K1 == 0)//k1按下
				{
					delay10ms();//消抖
					if(K1 == 0)//K1真的按下
					{
				     LED1 = 1;//让LED1亮
					   delay();
					}
				}
			}
			else//LED1灯是亮着的
			{
				if(K1 == 0)//
				{ 
					delay10ms();
					if(K1 == 0)
					{
				      LED1 = 0;//让LED1灯熄灭
					    delay();
					}
				}
			}
}		
void main(void)
{
	unsigned char val[10]= {0xc0,0xf9,0xa4,0xb0,0x99,
  0x92,0x82,0xf8,0x80,0x90};//0~9的数码表
	
	IT0 = 1;
	EX0 = 1;
	EA = 1;
	while(1)
	{
			unsigned char i;
			for(i=0 ;i<=9 ;++i)//主线任务
			{
				P0 = val[i];//数码管不断循环显示0到9
					delay();	
			}
			
  }
}

你可能感兴趣的:(第一季51单片机,单片机,嵌入式硬件,c语言)