对于c51外部中断和程序调用的理解

对于c51外部中断和程序调用的理解


徐晓峰

首先介绍一下C51外部中断的基本概念

  • 中断的优点:
    1、实时处理。需要CPU立即做出相应或处理。
    2、异常处理。运行过程中,出现断电、程序出错等问题,就需要CPU对故障源进行处理。
    3、提高效率。采用中断技术可以大大提高CPU的运行效率。

  • 中断源:C51单片机有5个中断源(2个外部中断、2个定时器中断和一个串口中断)。对中断的配置操作,主要通过控制三个寄存器就可以(中断允许寄存器IE)、定时器控制寄存器(TCON)和中断优先级寄存器(IP)。即通过控制EA EX IT 的直接赋值,即可调用中断服务程序
    注:中断服务程序与while(1)中的程序调用是不一样的

  • 中断服务函数:在CPU接收到中断后,会执行相应中断的中断服务函数。而C51的中断服务函数需要在函数名括号后面加上interrupt 和标志号,即interrupt 0、interrupt 1。

//外部中断0程序:
EA=1;//打开总中断开关
EX0=1;//开外部中断0
IT0=0/1;//设置外部中断的触发方式```

//外部中断1程序:
EA=1;//打开总中断开关
EX1=1;//开外部中断0
IT1=0/1;//设置外部中断的触发方式

//外部中断0服务函数:
void EX0_ISR(void) interrupt 0
	{
	
	}
	
 //外部中断1服务函数:
void EX1_ISR(void) interrupt 2     //外部中断1的中断在此为2!!!! 
	{
	
	}

其次来说一下"真假"中断

外部中断的调用主要分为两种,

  • 一种是调用外部中断来作为定时器,较为精确的计时;
  • 另一种是将函数写在中断服务函数中,调用外部中断进行函数的执行。

下面举例程序,经过两个不同方式外部中断的调用,达到同一个效果。

首先是proteus原理图的建立,如图

在这里插入图片描述

方式一,通过外部中断建立较为精准的计时,在while(1)中进行程序的执行。

#include <REGX51.H>

#define  uchar unsigned char
#define ledPort  P0
sbit LED = P0^0;
sbit button = P3^2;
void delay_ms(uchar ms);
uchar scan_key();
void initTimer(void);

unsigned int g_uiCount;
uchar delay_6ms;
uchar g_keys[3];

void main()
{
	uchar uci,ucDir=0;
	initTimer();
	TR0=1;
	ET0=1;
	EA=1;
    uci=0;
   while(1)
   {
	  if(g_keys[0]==1)
			{
					g_keys[0]=0;
				//°´¼ü´¦Àí
				if(ucDir==0)
					{
						ucDir=1;
					}	
				else
					{
						ucDir=0;
					}
			}
	  if(g_uiCount==500)
			{
				g_uiCount=0;
				if(ucDir)
					{
						ledPort = ~(1<<uci) ;
						uci=(uci+1)%8;
					} 
				else
					{
						uci=uci;
					}
			}
   }
}	
void initTimer(void)
{
 TMOD=0x1;
 TH0=0xfc;
 TL0=0x18;
}

void fun_6ms_isf();
void timer0(void) interrupt 1
{
  TH0=0xfc;
  TL0=0x18;
  g_uiCount++;
  if(++delay_6ms==6)
  {
  	delay_6ms=0;
		fun_6ms_isf();
  }
}

uchar get_key()
{
	button=1;
	if(button==0)
		{
				return 1;
		}
	else 
		{
				return 0;
		}
}

void fun_6ms_isf()
{
	 uchar key;
	 key=get_key();
	 if(key==1)
		 {
			if(g_keys[0]==0x80)
				{
					 g_keys[0]=1;
				}	
		 }
	 else
		 {
				g_keys[0]=0x80;
		 }
}		   

方式二,将程序直接写在外部中断中

#include <REGX51.H>
#define  uchar unsigned char
#define ledPort  P0
sbit LED = P0^0;

unsigned int g_uiCount; //¼ÆÊýÁ¿
void main()
{
	uchar uci,ucDir=0;
	EA=1;
	EX0=1;   
	IT0=0;  
  uci=0;
  while(1){}
}	

void timer0(void) interrupt 0
{
		uchar uci,ucDir=0;
    g_uiCount++;
  	  if(g_uiCount==5000)
	  {
	  	g_uiCount=0;
			ledPort = ~(1<<uci) ;
			uci=(uci+1)%8;
	  }
}


程序功能:

两组程序的效果一模一样,都是在有按键控制的情况下,按下按键,流水灯开始运行,当按键没有按下时,流水灯停止在当前的LED灯上,待下次继续按下时,流水灯继续执行。

  • 但需注意的是第一方法的程序除了上述流水灯功能外,无法同时执行其他的程序,但第二个方法的程序就可以在while(1)主程序中添加其余程序,使之在按键按下的时候执行流水灯程序,其余时刻执行主程序。、

所以可以说方法一的程序是"假"中断程序,而方法二的程序才是"真"中断程序。


总结

C51单片机,仅仅有两个外部中断,非常适合理解外部中断、中断服务函数的概念。多次调用中断程序,可以使C51程序编写更加有条理性。

若将所有需要执行的语句,以及其条件判断语句统统放在while(1)中,不仅使得编写的程序看起来臃肿、无条理性,更容易使时序产生误差。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值