51单片机中断及定时计数详解

目录

一、51单片机的中断

1.中断是什么

2.单一外中断实验示例

3.两个外中断实验示例

4.中断嵌套实验示例 

二、定时器

1.51单片机定时器结构

2.定时器0.5s中断实现以及在keil示波器上验证

 3.计数器中断控制LED


一、51单片机的中断

1.中断是什么

        中断技术主要用于实时监测与控制,要求单片机能及时地响应中断请求源提出的服务请求,并快速响应与及时处理。      

       当中断请求源发出中断请求时,如中断请求被允许,单片机暂时中止当前正在执行的主程序,转到中断服务处理程序处理中断服务请求,处理完中断服务请求后,再回到原来被中止的程序之处(断点),继续执行被中断的主程序。

2.单一外中断实验示例

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

       简化题目,要求P1端口8个LED灯常亮,在P3.2引脚设置一个按钮,按下按钮时P1端口的8个LED灯会变成高四位的LED和低四位的LED来回闪烁5次,最后返回常亮状态,

实现代码如下:

#include <reg51.h>
#define uchar  unsigned char
void Delay(unsigned int i)	
{	
  unsigned int j;
  for(;i > 0;i--)		
  for(j=0;j<333;j++)//晶振为12MHz,j和i越大延时越久
  {;}               //空操作,用来消耗时间达到延时效果
}
 
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上进行实验

Proteus连接图如下:

3.两个外中断实验示例

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

      本题用到了两个中断源,这两个中断源优先级是相同的,也就是一个中断源不会中断另一个中断源,我们只需要在上一道题一个中断源的基础上再加一个中断源就行了。

#include <reg51.h>
#define uchar unsigned char
void Delay(unsigned int 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;			 	
 EX1=1;	
 IT0=1;      	          	
 IT1=1;			 	
 IP=0;			 
 for(a=0;a<9;a++)
  {
  	Delay(500);			
  	P1=display[a];	
  }
}
void int0_isr(void)  interrupt 0  using 1//中断0的中断函数
{	
  uchar  n;
  for(n=0;n<10;n++)		
  {
  	 P1=0x0f; 		
  	 Delay(500);		
  	 P1=0xf0;		
  	 Delay(500);		
  } 
}
void int1_isr (void)  interrupt 2  using 2//中断1的中断函数
{	
  uchar  m;
  for(m=0;m<10;m++)				
   {
  	P1=0xff;				
   	Delay(500);				
   	P1=0;					
   	Delay(500); 				
  }
}

Proteus图如下:

4.中断嵌套实验示例 

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

       这题较上题涉及到了优先级,因此我们需要设置高优先级和低优先级。

#include <reg51.h>
#define uchar unsigned char
void Delay(unsigned int 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;			 	
  EX1=1;		          
  IT0=1;			 
  IT1=1;			 	
  PX0=0;			//中断源0低优先级
  PX1=1;			//中断源1高优先级	
for(a=0;a<9;a++)
  {
  	Delay(500);			
  	P1=display[a];	
  }
}
}
void int0_isr(void)  interrupt 0  using 1
{	
  uchar  n;
  for(n=0;n<10;n++)	
  {
  	P1=0x0f; 		
  	Delay(500);		
  	P1=0xf0;		
  	Delay(500);		
  } 
}
void int1_isr (void)  interrupt 2  using 2
{	
  uchar  m;
  for(m=0;m<10;m++)				
  {
  	P1=0xff;				
   	Delay(500);				
   	P1=0;					
   	Delay(500); 				
  }
}

下面是Proteus演示:

二、定时器

1.51单片机定时器结构

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

        T0、T1都有定时器和计数器两种工作模式,两种模式实质都是对脉冲信号进行计数,只不过计数信号来源不同。

        计数器模式是对加在T0(P3.4)和T1(P3.5)两个引脚上的外部脉冲进行计数。

        定时器模式是对系统时钟信号经12分频后的内部脉冲信号(机器周期)计数。由于系统时钟频率是定值,可根据计数值计算出定时时间。两个定时器/计数器属于增1计数器,即每计一个脉冲,计数器增1。 

        T0、T1具有4种工作方式 ,特殊功能寄存器TMOD用于选择定时器/计数器T0、T1的工作模式和工作方式。

2.定时器0.5s中断实现以及在keil示波器上验证

代码实现如下:

#include<reg51.h>
char  i=100;
void main ()
{
	TMOD=0x01;	
	TH0=0xee;			
	TL0=0x00;
P1=0x00;		
	EA=1;			
	ET0=1;		
	TR0=1;					
	while(1);		
	{
		;
	}
}
void timer0() interrupt 1	
{
	TH0=0xee;				
	TL0=0x00;
	i--;					
	if(i<=0)
	{
		P1=~P1;	
		i=100;		
	}
}

我们打开keil软件,使用keil软件自带的虚拟逻辑示波器功能可以得到P1端口波形变化

效果图如下:

100次中断时间间隔差不多在0.5s左右,可以看到,误差是很小的。

 3.计数器中断控制LED

       题目:T1采用计数模式,方式1中断,计数输入引脚T1(P3.5)上外接按钮开关,作为计数信号输入。按4次按钮开关后,P1口的8只LED闪烁不停。

       这里我们可以用计数器。

代码如下:

#include <reg51.h>
void Delay(unsigned int i)
{	
	unsigned int j;		
	for(;i>0;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 
	}							
}

Proteus仿真如下:

作者:建筑玩家

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机中断及定时计数详解

发表回复