中断与定时计数

本文详细介绍了51单片机中断机制,包括外部中断、定时器/计数器中断的编程实践,如定时1s点亮LED灯和按键触发LED闪烁。还探讨了如何优化中断函数,避免软件延时影响效率,通过硬件计时实现高效LED控制。
摘要由CSDN通过智能技术生成

中断与定时计数

一、实验目的

深入了解51单片机中断原理。掌握外部中断、定时器/计数器中断的编程方式;

了解中断响应、中断优先级、中断标志位复位等原理,掌握二级中断、中断嵌套的具体应用编程;

了解定时器/计数器的工作原理,掌握计数器初值计算方法,定时/计数中断服务的编程开发。

二、 具体任务

1、在Proteus和普中单片机板上分别完成采用定时计数器控制LED灯每隔1s周期性亮灭的实验。要求Keil仿真中的虚拟逻辑仪对LED管脚进行波形观察,测量真实的周期数。

代码如下:

#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++)
   	{;}
  }
 
void main( )
  {
  	EA=1;
   	EX0=1;
   	IT0=1;
		while(1)
			{P1=0;}
  }

 void int0( ) interrupt 0 using 0
  {
		uchar m;
		EX0=0;
   	for(m=0;m<5;m++)
		{
  	P1=0x0f;
   	Delay(400);
   	P1=0xf0;
   	Delay(400);
   	EX0=1;
    }
	}

在proteus中仿真如下:

请添加图片描述

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

代码如下:

#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
  {	
  	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中仿真如下:

请添加图片描述

3、一般来说,中断函数中要尽量避免使用执行时间较长(耗时)的代码,以避免中断服务影响到主程序代码的执行效率。但是在上面外部中断的实验中,中断函数采用了软件延时函数去控制LED亮灭的间隔周期。这是一种不好的编程。换一种更合理的方式,不在中断函数使用延时循环,实现同样的功能。

#include <reg51.h>
 
sbit LED = P1^0; 
 
volatile unsigned char mode = 0; 
 
void Delay(unsigned int i) {
    unsigned int j;
    for(;i>0;i--)
        for(j=0;j<125;j++)
            ;
}
 
void main() {
    TMOD = 0x50;     
    TH1 = 0xff;      
    TL1 = 0xfc;
    EA = 1;          
    ET1 = 1;         
    TR1 = 1;        
 
    while(1) {
        switch(mode) {
            case 0: // 
                LED = 0;
                break;
            case 1: // 
                LED = 1;
                break;
            case 2: // 
                LED = ~LED; 
                Delay(500);
                break;
        }
    }
}
 
void T1_int(void) interrupt 3 {
    static unsigned int counter = 0;
 
    counter++;
    if(counter >= 1000) { 
        counter = 0;
        mode = (mode + 1) % 3;
  }
}

在修改后的代码中,我们使用了一个全局变量mode来表示当前的LED模式。这样,中断服务程序就非常快,不会占用太多时间,而LED的控制逻辑则交由主循环处理。这种设计更加合理,能够保证中断的快速响应,并且不会影响到主循环的执行。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值