51单片机中断系统与定时计数的应用实验【Proteus】【普中51开发板】

51单片机中断系统与定时计数的应用实验【Proteus】【普中51开发板】

Proteus仿真实验

1. 单一外中断的应用

单片机对外设中断服务请求的整个中断响应和处理过程如下图。

在这里插入图片描述

实验电路

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

该电路的Proteus电路图如下。

在这里插入图片描述

实验程序

该电路的C程序如下。在Keil中编译以下程序,生成hex文件。

#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中断
	}
}
实验结果

将生成的hex文件导入Proteus电路中的单片机并仿真运行,结果如下。

在这里插入图片描述

2. 两个外中断的应用

当需要多个中断源时,只需增加相应的中断服务函数即可。

实验电路

在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接有一只按钮开关。在外部中断1输入引脚(P3.3)接有一只按钮开关。要求两只开关都未按下时,P1口的8只LED呈流水灯显示,仅开关P3.2按下再松开时,上下各4只LED交替闪烁10次,然后再回到流水灯显示。如果按下再松开开关P3.3时,P1口的8只LED全部闪烁10次,然后再回到流水灯显示。设置两个外中断的优先级相同。

该电路的Proteus电路图如下。

在这里插入图片描述

实验程序

该电路的C程序如下。在Keil中编译以下程序,生成hex文件。

#include <reg51.h>
#define uchar unsigned char
void Delay(unsigned int i)		//延时函数Delay( ),i为形式参数,不能赋初值
{	
	uchar j;
	for(;i>0;i--)
	for(j=0;j<125;j++)
	{;}				//空函数
}
void  main( )					//主函数
{
	uchar display[9]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf, 0x7f}; //流水灯显示数据数组
unsigned int a;
	for(;;)
	{
		EA=1;			 	//总中断允许
		EX0=1;			 	//允许外部中断0中断
		EX1=1;		          	//允许外部中断1中断
		IT0=1;			 	//选择外部中断0为跳沿触发方式
		IT1=1;			 	//选择外部中断1为跳沿触发方式
		IP=0;			 //两个外部中断均为低优先级
		for(a=0;a<9;a++)
		{
			Delay(500);			//延时
			P1=display[a];	//将已经定义的流水灯显示数据送到P1口
		}
	}
}
void int0_isr(void)  interrupt 0  using 1//外中断0的中断服务函数
{	
	uchar  n;
	for(n=0;n<10;n++)		//高、低4位显示10次
	{
		P1=0x0f; 		//低4位LED灭,高4位LED亮
		Delay(500);		//延时
		P1=0xf0;		 //高4位LED灭,低4位LED亮
		Delay(500);		//延时
	}
}
void int1_isr (void)  interrupt 2  using 2//外中断1中断服务函数
{	
	uchar  m;
	for(m=0;m<10;m++)				//闪烁显示10次
	{
		P1=0xff;				//全灭
		Delay(500);				//延时
		P1=0;					//全亮
		Delay(500); 				//延时
	}
}
实验结果

将生成的hex文件导入Proteus电路中的单片机并仿真运行,结果如下。

在这里插入图片描述

3. 两级中断嵌套的应用

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

在这里插入图片描述

实验电路

在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接有一只按钮开关。在外部中断1输入引脚(P3.3)接有一只按钮开关。要求两只开关都未按下时,P1口的8只LED呈流水灯显示,当按一下开关P3.2时,产生一个低优先级外中断0请求(跳沿触发),进入外中断0中断服务程序,上下4只LED交替闪烁。此时按一下开关P3.3时,产生一个高优先级的外中断1请求(跳沿触发),进入外中断1中断服务程序,使8只LED全部闪烁。当显示5次后,再从外中断1返回继续执行外中断0中断服务程序,即P1口控制8只LED,上、下4只LED交替闪烁。设置外中断0为低优先级,外中断1为高优先级。该电路的Proteus电路图如下。

在这里插入图片描述

实验程序

该电路的C程序如下。在Keil中编译以下程序,生成hex文件。

#include <reg51.h>
#define uchar unsigned char
void Delay(unsigned int i)		//延时函数Delay( )
{	
	unsigned int j;
	for(;i > 0;i--)		
	for(j=0;j<125;j++)		
	{;}					//空函数
}
void  main( )		//主函数
{
	uchar display[9]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯显示数据组		
	uchar a;
	for(;;)		
	{
		EA=1;			//总中断允许
		EX0=1;			//允许外部中断0中断
		EX1=1;			//允许外部中断1中断
		IT0=1;			//选择外部中断0为跳沿触发方式
		IT1=1;			//选择外部中断1为跳沿触发方式
		PX0=0;			//外部中断0为低优先级
		PX1=1;			//外部中断1为高优先级
		for(a=0;a<9;a++)		
		{					
			Delay(500);		//延时
			P1=display[a];		//流水灯显示数据送到P1口驱动LED显示
		}
	}
}

void int0_isr(void)  interrupt 0  using 0   //外中断0中断函数
{	
	for(;;)
	{
		P1=0x0f;		//低4位LED灭,高4位LED亮
		Delay(400);		//延时
		P1=0xf0;		//高4位LED灭,低4位LED亮
		Delay(400);		//延时
	} 							
}
void int1_isr (void)  interrupt 2  using 1  //外中断1中断函数
{
	uchar m;
	for(m=0;m<5;m++)			//8位LED全亮全灭5次
	{
		P1=0;				//8位LED全亮
		Delay(500);			//延时
		P1=0xff;			//8位LED全灭
		Delay(500);			//延时
	}
}
实验结果

将生成的hex文件导入Proteus电路中的单片机并仿真运行,结果如下。

在这里插入图片描述

4. 定时器的应用

实验电路

在AT89C51的P1口上接有8只LED,采用T0方式1的定时中断方式,使P1口外接的8只LED每0.5s闪亮一次。该电路的Proteus电路图如下。

在这里插入图片描述

实验程序

T0工作在方式1,应使TMOD寄存器的M1, M0=01;应设置C/T*=0,为定时器模式;对T0的运行控制仅由TR0来控制,应使相应的GATE位为0。定时器T1不使用,各相关位均设为0。所以,TMOD寄存器应初始化为0x01。

设定时时间5ms(即5000µs),设T0计数初值为X,假设晶振的频率为11.0592MHz,由公式定时时间=(216−X)×12/晶振频率,得定时时间为(216−X)×12/11.0592,解得X=60928,转换成十六进制为0xee00,其中0xee装入TH0,0x00装入TL0。

本例由于采用定时器T0中断,因此需将IE寄存器中的EA、ET0位置1。将定时器控制寄存器TCON中的TR0=1,则启动定时器T0;TR0=0,则停止定时器T0定时。

综上,该电路的C程序如下。在Keil中编译以下程序,生成hex文件。

#include<reg51.h>
char  i=100;
void main ()
{
	TMOD=0x01;			//定时器T0为方式1
	TH0=0xee;			//设置定时器初值
	TL0=0x00;
	P1=0x00;				//P1口8个LED点亮
	EA=1;					//总中断开
	ET0=1;					//开T0中断
	TR0=1;					//启动T0
	while(1);				//循环等待
	{
		;
	}
}
void timer0() interrupt 1			//T0中断程序
{
	TH0=0xee;				//重新赋初值
	TL0=0x00;
	i--;					//循环次数减1
	if(i<=0)
	{
		P1=~P1;			//P1口按位取反
		i=100;				//重置循环次数
	}
}
实验结果

将生成的hex文件导入Proteus电路中的单片机并仿真运行,结果如下。

在这里插入图片描述

在Keil中开启调试,使用波形图对信号P2监测,得波形图如下。波形图的每个周期时长约为0.47s,略低于0.5s.
在这里插入图片描述

5. 计数器的应用

实验电路

在AT89C51的P1口上接有8只LED,T1采用计数模式,方式1中断,计数输入引脚T1(P3.5)上外接按钮开关,作为计数信号输入。按4次按钮开关后,P1口的8只LED闪烁不停。该电路的Proteus电路图如下。

在这里插入图片描述

实验程序

T1工作在方式1,应使TMOD寄存器的M1, M0=01;应设置C/T*=1,为计数器模式;对T0的运行控制仅由TR0来控制,应使GATE0=0。定时器T0不使用,各相关位均设为0。所以,TMOD寄存器应初始化为0x50。

由于每按1次按钮开关,计数1次,按4次后,P1口的8只LED闪烁不停。因此计数器初值为65536−4=65532,将其转换成十六进制后为0xfffc,所以,TH0=0xff,TL0=0xfc。

本例由于采用T1中断,因此需将IE寄存器的EA、ET1位置1。将寄存器TCON中TR1=1,则启动T1计数;TR1=0,则停止T1计数。

综上,该电路的C程序如下。在Keil中编译以下程序,生成hex文件。

#include <reg51.h>
void Delay(unsigned int i)		//定义延时函数Delay( ),i是形式参数,不能赋初值
{	
	unsigned int j;		
	for(;i>0;i--)		//变量i由实际参数传入一个值,因此i不能赋初值
	for(j=0;j<125;j++)		
	{;}					//空函数
}

void  main( )			//主函数
{
	TMOD=0x50;			//设置定时器T1为方式1计数
	TH1=0xff;			//向TH1写入初值的高8位
	TL1=0xfc;			//向TL1写入初值的低8位
	EA=1;    			//总中断允许
	ET1=1;   			//定时器T1中断允许  
	TR1=1;   			//启动定时器T1
	while(1) ;		  	//无穷循环,等待计数中断
}

void T1_int(void)  interrupt 3  	//T1中断函数
{
	for(;;)					//无限循环
	{
		P1=0xff;			//8位LED全灭
		Delay(500) ;		//延时500ms
		P1=0;				//8位LED全亮
		Delay(500); 		//延时500ms
	}
}
实验结果

将生成的hex文件导入Proteus电路中的单片机并仿真运行,结果如下。

在这里插入图片描述

普中51开发板实验

普中51开发板资料:https://pan.baidu.com/s/1t4M7p-WfYE7tDi36qqa-cQ?pwd=1234 提取码:1234

普中51开发板如下图所示。开发板软件的使用方法见:https://blog.csdn.net/cqjtu_pengzifu/article/details/136992942

在这里插入图片描述

普中51开发板上的8个LED接在单片机的P2接口上。开发板的左下角有4个黑色按钮K1, K2, K3, K4, 分别接在单片机的P3.1, P3.0, P3.2, P3.3接口上。因此每个实验需将其实验程序中的P1改为P2,并在程序中加入以下语句:

sbit LED1=P2^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;

实验时,连接普中51开发板与电脑,将生成的hex文件下载至普中51开发板的单片机即开始运行。

1. 单一外中断的应用

实验程序
#include <reg51.h>
#define uchar  unsigned char
sbit LED1=P2^0;
sbit KEY3=P3^2;
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)		//循环
	{P2=0;}			// P2口的8只LED全亮
}

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

在这里插入图片描述

2. 两个外中断的应用

实验程序
![VID_20240407144107 -small-original](E:\13352\Pictures\动图\VID_20240407144107 -small-original.gif)#include <reg51.h>
#define uchar unsigned char
sbit LED1=P2^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
void Delay(unsigned int i)		//延时函数Delay( ),i为形式参数,不能赋初值
{	
	uchar j;
	for(;i>0;i--)
	for(j=0;j<125;j++)
	{;}				//空函数
}
void  main( )					//主函数
{
	uchar display[9]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf, 0x7f}; //流水灯显示数据数组
unsigned int a;
	for(;;)
	{
		EA=1;			 	//总中断允许
		EX0=1;			 	//允许外部中断0中断
		EX1=1;		          	//允许外部中断1中断
		IT0=1;			 	//选择外部中断0为跳沿触发方式
		IT1=1;			 	//选择外部中断1为跳沿触发方式
		IP=0;			 //两个外部中断均为低优先级
		for(a=0;a<9;a++)
		{
			Delay(500);			//延时
			P2=display[a];	//将已经定义的流水灯显示数据送到P2口
		}
	}
}
void int0_isr(void)  interrupt 0  using 1//外中断0的中断服务函数
{	
	uchar  n;
	for(n=0;n<10;n++)		//高、低4位显示10次
	{
		P2=0x0f; 		//低4位LED灭,高4位LED亮
		Delay(500);		//延时
		P2=0xf0;		 //高4位LED灭,低4位LED亮
		Delay(500);		//延时
	}
}
void int1_isr (void)  interrupt 2  using 2//外中断1中断服务函数
{	
	uchar  m;
	for(m=0;m<10;m++)				//闪烁显示10次
	{
		P2=0xff;				//全灭
		Delay(500);				//延时
		P2=0;					//全亮
		Delay(500); 				//延时
	}
}
实验结果

在这里插入图片描述

3. 两级中断嵌套的应用

实验程序
#include <reg51.h>
#define uchar unsigned char
sbit LED1=P2^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
void Delay(unsigned int i)		//延时函数Delay( )
{	
	unsigned int j;
	for(;i > 0;i--)		
	for(j=0;j<125;j++)		
	{;}					//空函数
}
void  main( )		//主函数
{
	uchar display[9]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯显示数据组		
	uchar a;
	for(;;)		
	{
		EA=1;			//总中断允许
		EX0=1;			//允许外部中断0中断
		EX1=1;			//允许外部中断1中断
		IT0=1;			//选择外部中断0为跳沿触发方式
		IT1=1;			//选择外部中断1为跳沿触发方式
		PX0=0;			//外部中断0为低优先级
		PX1=1;			//外部中断1为高优先级
		for(a=0;a<9;a++)		
		{					
			Delay(500);		//延时
			P2=display[a];		//流水灯显示数据送到P2口驱动LED显示
		}
	}
}

void int0_isr(void)  interrupt 0  using 0   //外中断0中断函数
{	
	for(;;)
	{
		P2=0x0f;		//低4位LED灭,高4位LED亮
		Delay(400);		//延时
		P2=0xf0;		//高4位LED灭,低4位LED亮
		Delay(400);		//延时
	} 							
}
void int1_isr (void)  interrupt 2  using 1  //外中断1中断函数
{
	uchar m;
	for(m=0;m<5;m++)			//8位LED全亮全灭5次
	{
		P2=0;				//8位LED全亮
		Delay(500);			//延时
		P2=0xff;			//8位LED全灭
		Delay(500);			//延时
	}
}

实验结果

在这里插入图片描述

4. 定时器的应用

实验程序
#include<reg51.h>
sbit LED1=P2^0;
char  i=100;
void main ()
{
	TMOD=0x01;			//定时器T0为方式1
	TH0=0xee;			//设置定时器初值
	TL0=0x00;
	P2=0x00;				//P2口8个LED点亮
	EA=1;					//总中断开
	ET0=1;					//开T0中断
	TR0=1;					//启动T0
	while(1);				//循环等待
	{
		;
	}
}
void timer0() interrupt 1			//T0中断程序
{
	TH0=0xee;				//重新赋初值
	TL0=0x00;
	i--;					//循环次数减1
	if(i<=0)
	{
		P2=~P2;			//P2口按位取反
		i=100;				//重置循环次数
	}
}
实验结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值