51单片机中断原理,中断相关应用编程及中断嵌套编程开发

目录

一、中断原理

1.1AT89C51中断技术:

1.2中断系统结构:

1.3中断寄存器:

1.3.1TCON寄存器:

1.3.2SCON寄存器:

1.3.3.中断优先级寄存器IP

1.4 响应中断请求的条件

二、外部中断应用编程

2.1单一外中断应用:

2.2两个外中断:

2.3中断嵌套:

三、定时器、计数器工作原理和编程开发

3.1定时器/计数器的结构

3.2定时器、计数器应用:

3.2.1定时器T0中断:

3.2.2计数器T0中断

3.3、中断优化

相关工程文件,希望能对你有所帮助:

链接: https://pan.baidu.com/s/1rBbvGidtrSRfYi8ToJDMEA?pwd=v6qn 提取码: v6qn 复制这段内容后打开百度网盘手机App,操作更方便哦 
--来自百度网盘超级会员v1的分享

一、中断原理

1.1AT89C51中断技术:

 中断技术主要用于实时监测与控制,要求单片机能及时地响应中断请求源提出的服务请求,并快速响应与及时处理。       当中断请求源发出中断请求时,如中断请求被允许,单片机暂时中止当前正在执行的主程序,转到中断服务处理程序处理中断服务请求,处理完中断服务请求后,再回到原来被中止的程序之处(断点),继续执行被中断的主程序。中断过程如下图所示:

1.2中断系统结构:

中断原理:

(1)INT0*—外部中断请求0,外部中断请求信号(低电平或负跳变有效)由INT0*引脚输入,中断请求标志为IE0。

(2)INT1*—外部中断请求1,外部中断请求信号(低电平或负跳变有效)由INT1*引脚输入,中断请求标志为IE1。

(3)定时器/计数器T0计数溢出的中断请求,标志为TF0。

(4)定时器/计数器T1计数溢出的中断请求,标志为TF1。

(5)串行口中断请求,标志为发送中断TI或接收中断RI。

1.3中断寄存器:

1.3.1TCON寄存器:

串行口控制寄存器,字节地址为98H,可位寻址。SCON的低二位锁存串口的发送中断和接收中断的中断请求标志TI和RI,

为定时器/计数器的控制寄存器,字节地址为88H,可位寻址。既包括定时器/计数器T0、T1溢出中断请求标志位TF0和TF1,也包括两个外部中断请求的标志位IE1与IE0,还包括两个外部中断请求源的中断触发方式选择位。

1.3.2SCON寄存器:

串行口控制寄存器,字节地址为98H,可位寻址。SCON的低二位锁存串口的发送中断和接收中断的中断请求标志TI和RI,

1.3.3.中断优先级寄存器IP

 中断请求源有两个中断优先级,每一个中断请求源可由软件设置为高优先级中断或低优先级中断,也可实现两级中断嵌套。两级中断嵌套过程如下图所示

5个中断请求源的中断请求标志分别由特殊功能寄存器TCON和SCON相应位锁存

AT89S51片内有一个中断优先级寄存器IP,字节地址为B8H,可位寻址。只要用程序改变其内容,即可进行各中断源中断优先级设置,IP寄存器格式如下图所示:

中断优先级寄存器IP各位含义: (1)PS—串行口中断优先级控制位,1—高级;0—低级。

(2)PT1—T1中断优先级控制位,1—高级;0—低级。

(3)PX1—外部中断1中断优先级控制位,1—高级;0—低级。

(4)PT0—T0中断优先级控制位,1—高级;0—低级。    

(5)PX0—外部中断0中断优先级控制位,1—高级;0—低级。

中断入口:

1.4 响应中断请求的条件

一个中断源中断请求被响应,须满足以下必要条件:

(1)总中断允许开关接通,即IE寄存器中的中断总允许位EA=1。

(2)该中断源发出中断请求,即该中断源对应的中断请求标志为“1”。

(3)该中断源的中断允许位=1,即该中断被允许。

(4)无同级或更高级中断正在被服务。

二、外部中断应用编程

2.1单一外中断应用:

例子:

在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接一只按钮开关K1。要求将外部中断0设置为电平触发。程序启动时,P1口上的8只LED全亮。每按一次按钮开关K1,使引脚接地,产生一个低电平触发的外中断请求,在中断服务程序中,让低4位的LED与高4位的LED交替闪烁5次。然后从中断返回,控制8只LED再次全亮。

参考代码如下:

#include <reg51.h>
  #define uchar  unsigned char
  void Delay(unsigned int i)	//延时函数Delay( ),i形式参数,不能赋初值
  {	
  	unsigned int j;
   	for(;i > 0;i--)		
   	for(j=0;j<333;j++)         //晶振为12MHz,j选择与晶振频率有关
   	{;}			   //空函数
  }
 
void  main( )			//主函数
  {	
  	EA=1;			//总中断允许
   	EX0=1;			//允许外部中断0中断
   	IT0=1;			//选择外部中断0为跳沿触发方式
  	while(1)		//循环	
{ P1=0;}			// P1口的8只LED全亮
  }

 void int0( )  interrupt 0  using 0  	//外中断0的中断服务函数
  {	
  	uchar  m;
  	EX0=0;			//禁止外部中断0中断
   	for(m=0;m<5;m++)	//交替闪烁5次
  	{
  	    P1=0x0f;		//低4位LED灭,高4位LED亮
	Delay(400) ;		//延时
   	P1=0xf0;		//高4位LED灭,低4位LED亮
   	Delay(400); 		//延时
   	EX0=1;			//中断返回前,打开外部中断0中断
  }

Proteus仿真原理图:

结果展示:

烧录到C51中:(小组成员 @一瓶勇闯天涯的雪花 实现的)

2.2两个外中断:

当需要多个中断源时,只需增加相应的中断服务函数即可  【例】如图6-10所示,在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接有一只按钮开关K1。在外部中断1输入引脚(P3.3)接有一只按钮开关K2。要求K1和K2都未按下时,P1口的8只LED呈流水灯显示,仅K1(P3.2)按下再松开时,上下各4只LED交替闪烁10次,然后再回到流水灯显示。如果按下再松开K2(P3.3)时,P1口的8只LED全部闪烁10次,然后再回到流水灯显示。设置两个外中断的优先级相同。

仿真原理图:

Proteus仿真:

参考代码;

PPt中代码经过调试还是无法正常运行,我从网上其他地方找到一份keil代码:

#include <REGX52.H>

void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;//这是一个延时函数,用于产生一段时间的延时。函数接受一个参数 xms,表示要延时的毫秒数。
	while(xms--)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}


void main()
{
	EA=1;		//总中断打开
	EX0=1;
	EX1=1;	//	允许中断0、1中断
	IT0=1;
	IT1=1;	//中断0、1设置下降沿中断
	IP=0;		//中断优先级控制寄存器低(可位寻址)
	
	while(1)
	{
		P2=0xFE;//1111 1110
		Delay(500);
		P2=0xFD;//1111 1101
		Delay(500);
		P2=0xFB;//1111 1011
		Delay(500);
		P2=0xF7;//1111 0111
		Delay(500);
		P2=0xEF;//1110 1111
		Delay(500);
		P2=0xDF;//1101 1111
		Delay(500);
		P2=0xBF;//1011 1111
		Delay(500);
		P2=0x7F;//0111 1111
		Delay(500);		
	}//这是一个无限循环,不停地对 P2 端口输出不同的模式,然后延时一段时间。P2 端口是一个8位的输出端口。
}

	
void Int0_Routine() interrupt 0
{
	unsigned char i;
	for(i=0;i<10;i++)
	{
		P2=0xf0;
		Delay(300);
		P2=0x0f;
		Delay(300);
	}
}

void Int1_Routine() interrupt 2//这是外部中断1的中断服务函数,它被设置为在外部中断1触发时执行。
{	
			unsigned char i;
			for(i=0;i<10;i++)
			{
				P2=0xff;
				Delay(300);
				P2=0x00;
				Delay(300);
			}
}
	
	
	

导入hex文件,仿真实现:

2.3中断嵌套:

中断嵌套只发生正执行一个低优先级中断,此时又有一高优先级中断产生,就会去执行高优先级中断服务程序。高优先级中断服务程序完成后,再继续执行低优先级中断程序。

【例】电路见图6-10,设计一中断嵌套程序:要求K1和K2都未按下时,P1口8只LED呈流水灯显示,当按一下K1时,产生一个低优先级外中断0请求(跳沿触发),进入外中断0中断服务程序,上下4只LED交替闪烁。此时按一下K2时,产生一个高优先级的外中断1请求(跳沿触发),进入外中断1中断服务程序,使8只LED全部闪烁。当显示5次后,再从外中断1返回继续执行外中断0中断服务程序,即P1口控制8只LED,上、下4只LED交替闪烁。设置外中断0为低优先级,外中断1为高优先级。

在两个外部中断的基础上,修改中断优先级:调整代码即可实现中断嵌套:

修改代码如下:


IP=0; //中断优先级控制寄存器低(可位寻址)
//中断嵌套按要求设置为外部中断1优先级高于外部中断0
PX0=0;
PX1=1; //中断1优先于中断0

Proteus仿真得到

结果如图所示:

三、定时器、计数器工作原理和编程开发

3.1定时器/计数器的结构

AT89S51定时器/计数器结构见图 7-1,定时器/计数器T0由特殊功能寄存器TH0、TL0构成,T1由特殊功能寄存器TH1、TL1构成。

M1、M0 4种编码,对应于4种工作方式的选择:

3.2定时器、计数器应用:

3.2.1定时器T0中断:

要求 :在 Prodeus 和普中单片机板上分别完成采用定时计数器控制 LED 灯每隔 1S 周期性亮灭的实验。要 求KEIL 仿真中的虚拟逻辑仪对 LED 管脚进行波形观察,测量真实的周期数,并与软件循环进行周期定时 的精度进行对比,看哪一种方式更加精准。
定时器初值 :设定时时间 1ms ( 5000 μ s) ,设 T0 计数初值为 X ,假设晶振的频率为 11.0592MHz, 则定时时间为:
1000=(2^16 - X)*12/11.0592 ==> X=64614 ,转换为十六进制为 0xFC66 ,其中 0XFC 装入 TH0 ,0X66 装入 TL0
相关代码:
#include <REGX52.H>

void Timer0_Init()
{
	//设置定时器工作模式TMOD为方式1
	//TMOD为不可位寻址,只能整体赋值,可采用&=、|=使其只改变某些位
	TMOD&=0xf0;//高四位不变,低四位清零
	TMOD|=0x01;//最低位置1,其余位不变 //TOMD=0x01
	//定时时间=(2^16-X)*12/晶振频率
	TL0=0x66;
	TH0=0xfc;//定时1ms
	//设置定时器控制寄存器TCON
	TF0=0; //中断溢出标志位先清0,避免刚配置好就中断
	TR0=1; //定时器开始工作
	//中断
	EA=1;//允许总中断
	ET0=1;//T0的中断溢出允许位,T0=1,允许中断
}


void main()
{
	Timer0_Init();
	while(1)
	{
		
	}
}

void Timer0_Runtine() interrupt 1
{
	unsigned int Count;//计数
	TL0=0x66;
	TH0=0xfc;
	Count++;
	if(Count>=1000)//计数累加到1000,定时器定时1000ms=1s
	{
			P2_0=~P2_0;//LED状态取反
		Count=0;
	}
}

 点亮结果:

3.2.2计数器T0中断

要求
采用计数器中断,实现按 4 次按键开关后, P2 口的 8 LED 闪烁不停。
计数器初值 :由于每按 1 次按键开关,计数 1 次,按 4 次后, P2 口的 8 LED 闪烁不停。因此计数器初值为
2^16 - 4=65532 , 转化为十六进制后为 0XFFFC ,所以 TH0=0XFF TL0=0XFC

相关编程代码如下:

#include <REGX52.H>
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
			i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}


void Count0_Init()	//计数器
{
	//设置计数器0工作模式1
	TMOD&=0xf0;
	TMOD|=0x05;// C/T置1为计数器模式
	TL0=0xfc;
	TH0=0xff;//计数4次,65536-4=65532
	//设置计数器控制寄存器TCON
	TF0=0;
	TR0=1;
	//中断
	EA=1;
	ET0=1;
}

void main()
{
	Count0_Init();
	while(1)
	{
		
	}
}

void Count0_Routine() interrupt 1
{
	while(1)
	{
				P2=~P2;
				Delay(500);
				P2=~P2;
				Delay(500);
	}

}

3.3、中断优化

优化内容:

在上述的按键控制 LED 的实验中,中断函数采用了软件延时函数控制 LED 间隔周期,为了避免中
断服务程序执行较长耗时的代码,将外部中断程序进行优化:在中断服务程序中只改变中断模式标志 位,在主函数中根据不同的中断模式标志,选择不同的亮灯模式。

Keil代码实现:

#include <REGX52.H>

void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

void Init0()
{
	EA=1;
	EX0=1;
	IT0=1;//下降沿触发
}

unsigned char Key_Interrupt_Flag=0;//中断模式标志位

void Init0_Routine() interrupt 0
{
	Key_Interrupt_Flag=1;
}
	
void main()
{
	unsigned char Mode=0;
	Init0();
	while(1)
	{
		if(Key_Interrupt_Flag)//如果中断标志位为1 
		{
			Key_Interrupt_Flag=0;//标志位置0
			Mode++;//切换亮灯模式 
			if(Mode>=3)
			{
				Mode=0;//循环切换
			}
		}
		
		switch (Mode)//亮灯模式选择
		{
			case 0:
				{P2=0xfe;}
				break;
			case 1:
				{P2=0xf0;Delay(300);P2=0X0F;Delay(300);}
				break;
			case 2:
				{P2=0XAA;Delay(300);P2=0x55;Delay(300);}
				break;
			default:
				break;
		}	
	}
}

Proteus仿真结果:

烧录到普中开发板上:

完。

总结:

本次仿真实验,从多方面学习到了仿真实践,熟练掌握仿真、烧录流程,对汇编语言代码也进一步加深了理解,对51单片机的学习更进一步。

致读者:本人才疏学浅,若文章有不对的地方还望读者积极指出,感谢大家的批评指正。

参考文章:http://t.csdnimg.cn/HAjgX

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值