这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 高校专区 » 坤创E-Geek/天科大新电社 » 06. 单片机外部中断的使用

共10条 1/1 1 跳转至

06. 单片机外部中断的使用

高工
2019-01-25 17:20:05     打赏

今天收到同学们的支持和鼓励,大Z在此谢谢大家了。做这个帖子的初衷,就是为了给各位努力的同学们提供一个交流问题,分享问题,解决问题的平台。希望或多或少能够对大家有所帮助。曾子曰:大家好,才是真的好嘛!

今天的题目,主要是练习如何操作单片机的外部中断。曾子又曰:学单片机不学中断的话,就跟不会单片机没什么两样。可见中断在单片机学习体系中的地位有多么的重要。每年从蓝桥杯的竞赛题目来看,如果不会用中断,那么你基本上是没法完整的实现题目当中所要求的各项内容的。因此呢~中断也是必考点,当然也是必须要进行练习的要点之一。

那么如何使用中断解题,如何形成使用中断的编程思维,就显得尤为重要。下面咱们就来先针对练习题,把相关代码发给大家,请大家自行查看哈。本节的练习题要求如下。

题1、在数码管上显示字符8,按下外部按键中断0(S5)则8左移动,按下外部按键中断1(S4)则8右移动

题2、数码管初始显示0,按下外部按键中断0(S5),数值加1,按下外部按键中断1(S4),数值减1

下面仍照惯例给出两个题目的代码,并在文末给出所有代码压缩包的下载链接,想要源代码怎么操作,曾子曰:你懂的~

学习中如有任何问题,请大家在下方回帖告知~回帖有好礼,不要白不要呀~哈哈~~

-----------------------蓝桥板代码---------------------

蓝桥板题1代码:

/******************************************************************************************
1、在数码管上显示字符8,按下外部按键中断0(S5)则8右移动,按下外部按键中断1(S4)则8左移动
******************************************************************************************/
#include<stc15f2k60s2.h>
#include"intrins.h"

#define uchar unsigned char
#define uint  unsigned int 

uchar code smgwei[]={0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80,0X01};
uchar code smgtab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0XFF};
uchar s4,s5;
void init();//蓝桥杯板初始化程序
void keyScan();//键盘扫描
void int0Init();//外部中断0与1的初始化函数
void delayms(uint z);//ms级延时函数

/**************************主函数*****************************/
/*void main()
{
	uchar i;
	int0Init();
	init();
	while(1)
	{ 
		if(s4==1)             //左移动
		{
		uchar i=8;
		s4=0;
		do
		{
			P2=0xc0;
			P0=smgwei[i]; //位值
			P2=0xff;
			P0=0x80;     //段值8
			delayms(500);
		}while(i--);

		}
		else if(s5==1)      //右移动
		{
			s5=0;
			for(i=0;i<8;i++)
			{
				P2=0xc0;
				P0=smgwei[i]; //位值
				P2=0xff;
				P0=0x80;     //段值8
				delayms(500);
			} break;	 
		}	
		keyScan();
	}			
}
		 	 	 
void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=845;y>0;y--);
}
	
void init()
{
   P2=0xa0; 
	 P0=0x00;  //关闭继电器蜂鸣器
	 P2=0x80;
	 P0=0xff;  //关闭led灯
	 P2=0xc0;
	 P0=0xff; //选择所有数码管
	 P2=0xff;
	 P0=0xff; //关闭所有数码管
}

void int0Init()
{
	      //设置INT0
	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。	
	IT1=1;//设置INT1
	EX1=1;//打开INT1的中断允许。	
	EA=1;//打开总中断	
}

void int0()interrupt 0 
{
	EX0=0;
	s5=~s5;
	EX0=1;
}
void int1()interrupt 1
{
	EX0=0;
	s4=~s4;
	EX0=1;
}

void keyScan()
{
	if(P32==0)   //s5
	{
		delayms(5);
		if(P32==0)
		{
			s5=1;      //s5的标志位
		}
		while(!P32);
	}

	else if(P33==0)  //s4
	{
		delayms(5);
		if(P33==0)
		{
			s4=1;    //s4的标志位
		}
		while(!P33);
	}
}

蓝桥板题2代码:

/************************************************************************************
2、数码管初始显示0,按下外部按键中断0(S5),数值加1,按下外部按键中断1(S4),数值减1。
*************************************************************************************/
#include<stc15f2k60s2.h>
#include"intrins.h"

#define uchar unsigned char
#define uint  unsigned int 
	
uchar	code smgtab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar tt;
uchar s4,s5,num;
uchar yi,er,san,si,wu,liu,qi,ba;
void init();//蓝桥杯板初始化程序
void keyScan();//键盘扫描
void int0Init();//外部中断0与1的初始化程序
void delayms(uint z);//ms级延时函数
void  displayOne(uchar yi,uchar er);//第一 二个数码管显示函数
void  displayTwo(uchar san,uchar si);//第三 四个数码管显示函数
void  displayThree(uchar wu,uchar liu);//第五 六个数码管显示函数
void  displayFour(uchar qi,uchar ba);//第七 八个数码管显示函数

void main()
{
	init();
	int0Init();
	while(1)
	{
		yi=11;er=11;san=11;si=11;wu=11;liu=num/100;qi=num/10%10;ba=num%10;	 
		if(s5==1)   //外部中断加1
		{
			s5=0;
			if(num>=0&&num<255) num=num+1;	
			else if(num==255){num=255;}
		}
		else if(s4==1) //外部中断减1
		{
			s4=0;
			if(num>0&&num<=255)	num=num-1;
			else if(num==0){num=0;}
		}	
		keyScan();
		displayOne(yi,er);
		displayTwo(san,si);
		displayThree(wu,liu);
		displayFour(qi,ba);			    
	} 
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=845;y>0;y--);
}
	
void init()
{
	P2=0xa0; 
	P0=0x00;   //关闭继电器蜂鸣器
	P2=0x80;
	P0=0xff;  //关闭led灯
	P2=0xc0;
	P0=0xff; //选择所有数码管
	P2=0xff;
	P0=0xff; //关闭所有数码管
}

void keyScan()
{
	if(P32==0)   //s5
	{
		delayms(5);
		if(P32==0)
		{
			s5=1;     //按键s5的标志位
		}
		while(!P32);
	}

	else	if(P33==0)  //s4
	{
		delayms(5);
		if(P33==0)
		{
			s4=1;  //按键s4的标志位
		}
		while(!P33);
	}
}

void int0Init()
{
	      //设置INT0
	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。	
	IT1=1;//设置INT1
	EX1=1;//打开INT1的中断允许。	
	EA=1;//打开总中断	
}

void int0()interrupt 0
{
	EX0=0;
	s5=~s5;
	EX0=1;
}
void int1()interrupt 1
{
	EX0=0;
	s4=~s4;
	EX0=1;
}

void  displayOne(uchar yi,uchar er)
{
   P2=0xc0;
	 P0=0x01;     //选通第一个数码管
	 P2=0xff;
	 P0=smgtab[yi];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x02;    //选通第二个数码管
	 P2=0xff;
	 P0=smgtab[er];//位选
	 delayms(1);
}

void   displayTwo(uchar san,uchar si)
{
   P2=0xc0;
	 P0=0x04;     //选通第三个数码管
	 P2=0xff;
	 P0=smgtab[san];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x08;    //选通第四个数码管
	 P2=0xff;
	 P0=smgtab[si];//位选
	 delayms(1);
}

void   displayThree(uchar wu,uchar liu)
{
   P2=0xc0;
	 P0=0x10;   //选通第五个数码管
   P2=0xff;
	 P0=smgtab[wu];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x20;  //选通第六个数码管
	 P2=0xff;
	 P0=smgtab[liu];//位选
	 delayms(1);
}

void  displayFour(uchar qi,uchar ba)
{
   P2=0xc0;
	 P0=0x40;  //选通第七个数码管
	 P2=0xff;
	 P0=smgtab[qi];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x80;  //选通第八个数码管
	 P2=0xff;
	 P0=smgtab[ba];//位选
	 delayms(1);
}

-----------------------小红板代码----------------------

小红板题1代码:

/************************************************************************************
1、在数码管上显示字符8,按下外部按键中断0(S5)则8左移动,按下外部按键中断1(S10)则8右移动
*************************************************************************************/
#include"reg52.h"
#define uchar	unsigned char
#define uint  unsigned int 
	
sbit  s5=P3^0;
sbit  s10=P3^1;

sbit	P_HC595_SER   = P2^7;	//pin 14	SER		data input
sbit	P_HC595_RCLK  = P2^5;	//pin 12	RCLk	store (latch) clock
sbit	P_HC595_SRCLK = P2^6;	//pin 11	SRCLK	Shift data clock

uchar  code smgwei[]={0X00,0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F}; 

uchar i;
uchar ss5,ss10;
uchar yi,er,san,si,wu,liu,qi,ba;
void keyscan();//键盘扫描
void smg_Init();//数码管初始化
void int0Init();//外部中断0与1初始化
void delayms(uint z);//ms级延时函数
void Send_595(unsigned char dat);

/****************主函数***********************/
/*void main()
{
	smg_Init();
	int0Init();
	while(1)
	{
		if(ss5==1)
		{ 
			ss5=0;
			for(i=8;i>0;i--)     //左移
			{
				Send_595(smgwei[i]);   //位选
				Send_595(0x7f);       // 段选
				P_HC595_RCLK = 0;
				P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
				delayms(1000);
			}break;
		} 

		else if(ss10==1)
		{ 
			ss10=0;
			for(i=0;i<8;i++)     //右移
			{
				Send_595(smgwei[i]); 
				Send_595(0x7f);
				P_HC595_RCLK = 0;
				P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
				delayms(1000);
			}break;
		}
		keyscan();  
	}
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}

void keyscan()
{
	if(s5==0)         //s5
	{
		delayms(5);
		if(s5==0)
		{
			ss5=1;     //s5的标志位
		}
		while(!s5);
	}

	else if(s10==0)  //s10
	{
		delayms(5);
		if(s10==0)
		{
			ss10=1;   //s10的标志位
		}
	while(!s10);
	}
}

void smg_Init()
{
	Send_595(0x00);  //同时选择8个数码管
	Send_595(0x00);	 //让8个数码管同时显示消隐字符
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选	
}

void int0Init()
{
	      //设置INT0
	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。	
	IT1=1;//设置INT1
	EX1=1;//打开INT1的中断允许。	
	EA=1;//打开总中断	
}

void int0()interrupt 0
{
	EX0=0;
	ss5=~ss5;
	EX0=1;
}
void int1()interrupt 1
{
	EX0=0;
	ss10=~ss10;
	EX0=1;
}
void Send_595(unsigned char dat)	//发送一个字节
{		
	unsigned char	i;
	for(i=0; i<8; i++)
	{
		if(dat & 0x80)	    //判断dat的最高位是否为1
			P_HC595_SER = 1;  //最高位如果为1,则令P2.7 = 1
		else			
			P_HC595_SER = 0;  //最高位如果为0,则令P2.7 = 0
		
		P_HC595_SRCLK = 0;
		P_HC595_SRCLK = 1;
		P_HC595_SRCLK = 0;  //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端
		dat = dat << 1;     //将dat左移一位,取次高位
	}
}

小红板题2代码:

/*************************************************************************************
2、数码管初始显示0,按下外部按键中断0(S5),数值加1,按下外部按键中断1(S4),数值减1。
**************************************************************************************/
#include"reg52.h"

#define uchar	unsigned char
#define uint	unsigned int 

sbit	P_HC595_SER   = P2^7;	//pin 14	SER		data input
sbit	P_HC595_RCLK  = P2^5;	//pin 12	RCLk	store (latch) clock
sbit	P_HC595_SRCLK = P2^6;	//pin 11	SRCLK	Shift data clock

sbit  s5=P3^0;
sbit  s10=P3^1;
sbit  s15=P3^2;
sbit  s20=P3^3;

uchar  code smgtab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00};	
uchar ss5,ss10,num;
uchar yi,er,san,si,wu,liu,qi,ba;
void  keyscan();
void  smg_Init();//数码管初始化函数
void  int0Init();//外部中断0与1的初始化函数
void  delayms(uint z);//ms级延时函数
void  Send_595(unsigned char dat);
void  displayOne(uchar yi,uchar er);//第一 二个数码管显示函数
void  displayTwo(uchar san,uchar si);//第三 四个数码管显示函数
void  displayThree(uchar wu,uchar liu);//第五 六个数码管显示函数
void  displayFour(uchar qi,uchar ba);//第七 八个数码管显示函数

/**********************主函数*****************************/

void main()
{
	smg_Init();
	int0Init();
	while(1)
	{
		yi=11;er=11;san=11;si=11;wu=11;liu=num/100;qi=num/10%10;ba=num%10;

		if(ss5==1)   //外部中断加1
		{
			ss5=0;
			if(num>=0&&num<255) num=num+1;	
			else if(num==255){num=255;}
		}
		else if(ss10==1) //外部中断减1
		{
			ss10=0;
			if(num>0&&num<=255)	num=num-1;
			else if(num==0){num=0;}
		}	
		keyscan();
		displayOne(yi,er);
		displayTwo(san,si);
		displayThree(wu,liu);
		displayFour(qi,ba);
	}
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);

}

void keyscan()
{
	if(s5==0)   //s5
	{
		delayms(5);
		if(s5==0)
		{
		 ss5=1;    //按键s5的标志位
		}
		while(!s5);
	}

	else if(s10==0)  //s10
	{
		delayms(5);
		if(s10==0)
		{
			ss10=1;   //按键s10的标志位
		}
		while(!s10);
	}
}
void int0Init()
{
	      //设置INT0
	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。	
	IT1=1;//设置INT1
	EX1=1;//打开INT1的中断允许。	
	EA=1;//打开总中断	
}
void int0()interrupt 0
{
	EX0=0;
	ss5=~ss5;
	EX0=1;
}
void int1()interrupt 1
{
	EX0=0;
	ss10=~ss10;
	EX0=1;
}

void smg_Init()
{
	Send_595(0x00);  //同时选择8个数码管
	Send_595(0x00);	 //让8个数码管同时显示消隐字符
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选	
}


void Send_595(unsigned char dat)	//发送一个字节
{		
	unsigned char	i;
	for(i=0; i<8; i++)
	{
		if(dat & 0x80)	    //判断dat的最高位是否为1
			P_HC595_SER = 1;  //最高位如果为1,则令P2.7 = 1
		else			
			P_HC595_SER = 0;  //最高位如果为0,则令P2.7 = 0
		
		P_HC595_SRCLK = 0;
		P_HC595_SRCLK = 1;
		P_HC595_SRCLK = 0;  //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端
		dat = dat << 1;     //将dat左移一位,取次高位
	}
}


void  displayOne(uchar yi,uchar er)
{
	  Send_595(0xfe);     //选通第一个数码管
		Send_595(smgtab[yi]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
	
	  Send_595(0xfd);     //选通第二个数码管
		Send_595(smgtab[er]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
}

void  displayTwo(uchar san,uchar si)
{
	  Send_595(0xfb);    //选通第三个数码管
		Send_595(smgtab[san]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
	 
	  Send_595(0xf7);   //选通第四个数码管
		Send_595(smgtab[si]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
}

void  displayThree(uchar wu,uchar liu)
{
	  Send_595(0xef);   //选通第五个数码管
		Send_595(smgtab[wu]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
	
	  Send_595(0xdf);  //选通第六个数码管
		Send_595(smgtab[liu]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
}

void  displayFour(uchar qi,uchar ba)
{
	  Send_595(0xbf);   //选通第七个数码管
		Send_595(smgtab[qi]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
	
	  Send_595(0x7f);   //选通第八个数码管
		Send_595(smgtab[ba]);//段选
		P_HC595_RCLK = 0;
		P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(1);
}

----------------所有代码打包下载链接------------------

06单片机外部中断的使用_全部代码打包.zip

大家可以继续提前接着往下进行 07单片机定时计数器的使 的题目练习~如对代码有任何问题,请粗暴的指出来告诉我哦~

曾子最后曰:忍不住想夸大家一句,同学们奋斗的样子真美丽~




菜鸟
2019-01-25 22:37:01     打赏
2楼

看了一下老师的代码,关于小红板第一个题就学习中断还有标志位概念来说很有启发意义,实现功能而言感觉用中断有些太过繁琐。然后就自己试着改了一下纯按键实现,想简洁一点。小红板第二个题按照按键功能的思路也是感觉可以的。

(PS:今天的代码看起来好麻烦啊真是让老师辛苦了。)

以下是小红板第一个题的main()函数。

 

void main()  

{   smg_Init();   

    while(1)  

    {  

        if(s5==0) {    

            for(i=8;i>0;i--)  {  

                Send_595(smgwei[i]);   
                Send_595(0x7f);       

                P_HC595_RCLK = 0;  

                P_HC595_RCLK = 1; 
                delayms(1000);  

            }
        }   

        else if(s10==0) {    

            for(i=1;i<9;i++){ //smgwei[]={0X00,0XFE,0XFD,0XFB,0XF7,                                    0XEF,0XDF,0XBF,0X7F}; 

                Send_595(smgwei[i]);   

                Send_595(0x7f);  

                P_HC595_RCLK = 0;  

                P_HC595_RCLK = 1; 
                delayms(1000);  

            } 

        }    

    }  

}

 


院士
2019-01-27 09:40:33     打赏
3楼

祝老师 辛苦了


菜鸟
2019-02-02 10:37:44     打赏
4楼

遇到不会,实在想不到解决的办法 就会偷偷的来看一眼程序


院士
2019-02-11 09:57:47     打赏
5楼

放眼望去,论坛的精华帖子全被祝老师覆盖了


院士
2019-02-14 09:06:48     打赏
6楼

学习学习,谢谢分享!!


院士
2019-02-14 10:09:02     打赏
7楼

现在都不知道写什么啊


专家
2019-02-14 15:16:52     打赏
8楼

顶一个。。


工程师
2019-02-27 17:42:06     打赏
9楼
在void int0()interrupt 0 void int1()interrupt 1中怎么都是EX0 INT0中断允许。 EX1 INT1中断允许不用么?

菜鸟
2019-03-01 09:33:27     打赏
10楼

蓝桥杯的前两个程序外部中断用上了吗?我把中断的代码全都删了,程序依然是对的


共10条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]