中断与定时计数

一、中断、定时

1.中断系统

中断源级别入口地址
外部中断0最高0003H
T0溢出中断|000BH
外部中断1|0013H
T1溢出中断|001BH
串行口中断最低0023H

2.中断不被响应情况

在遇到以下三种情况时中断请求不会被响应

(1)CPU正在处理同级或更高优先级的中断。

(2)所查询的机器周期不是当前正在执行指令的最后一个机器周期

(3)正在执行的指令是RETI或是访问IE或IP的指令

3.定时器/计时器

(1)结构:AT89S51定时器/计数器T0由特殊功能寄存器TH0、TL0构成,T1由特殊功能寄存器TH1、TL1构成, T0、T1都有定时器和计数器两种工作模式,两种模式实质都是对脉冲信号进行计数,只不过计数信号来源不同,同时它们具有4种工作方式(方式0,1,2,3)

(2)计数器初值计算

T0计算计数器初值:定时时间=(216−X)×12/晶振频率

二、外部中断、二级中断

(参考课件上的外部中断、二级中断内容)

1.单一外中断

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

(1)proteus仿真电路图

在这里插入图片描述

(2)实现代码

 #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中断
  }

​ 本例程包含两部分,一部分是主程序段,完成中断系统初始化,并把8个LED全部点亮。另一部分是中断函数部分,控制4个LED交替闪烁1次,然后从中断返回。(注意:在后面的普中开发板实验实现时要根据开发板情况选择端口,在上述代码中使用端口为P1,但所使用开发板LED端口使用的是P2则在实现时应将上述代码中端口改为P2。以下全部代码同上)

(3)实践效果

Proteus仿真效果:

在这里插入图片描述

普中开发板实验效果:

在这里插入图片描述

2.两个外中断

在单片机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次,然后再回到流水灯显示。设置两个外中断的优先级相同。

(1)proteus仿真电路图

在这里插入图片描述

(2)实现代码

#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); 				//延时
  	}
  }

(3)实践效果

Proteus仿真效果:

在这里插入图片描述

普中开发板实验效果:

在这里插入图片描述

3.中断嵌套

设计一中断嵌套程序:要求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为高优先级。

(1)proteus仿真电路图

在这里插入图片描述

(2)实现代码

#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);			//延时
  }
}

中断嵌套只发生正执行一个低优先级中断,此时又有一高优先级中断产生,就会去执行高优先级中断服务程序。高优先级中断服务程序完成后,再继续执行低优先级中断程序,本例如设置外中断1为低优先级,外中断0为高优先级,仍然先按下再松开K1,后按下再松开K2或者设置两个外中断源的中断优先级为同级,均不会发生中断嵌套。

(3)实践效果

Proteus仿真效果:

在这里插入图片描述

普中开发板实验效果:

在这里插入图片描述

三、定时器/计数器

1.采用定时计数器控制LED灯周期性亮灭的实验

在AT89S51的P1口上接有8只LED,采用T0方式1的定时中断方式,使P1口外接的8只LED每1s闪亮一次。

(1)proteus仿真电路图

在这里插入图片描述

(2)实现代码

#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
	{
			P1_0=~P1_0;//LED状态取反
		Count=0;
	}
}

(代码参考:【51单片机】中断系统、定时器计数器工作原理及应用
)
(3)实践效果

Proteus仿真效果:

在这里插入图片描述

普中开发板实验效果:

在这里插入图片描述

2.采用计数器中断,实现 按4次按钮开关后,P1口的8只LED闪烁不停。

(1)proteus仿真电路图

在这里插入图片描述

(2)实现代码

    #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 
	}							
}

(3)实践效果

Proteus仿真效果:

在这里插入图片描述
四、总结
通过这次实验我学习到了更多关于中断系统和定时器的相关知识。

  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值