论坛» 高校专区» 坤创E-Geek/天科大新电社

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

高工
2019-01-25 17:20 1楼

今天收到同学们的支持和鼓励,大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 #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 #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 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 3楼

祝老师 辛苦了

菜鸟
2019-02-02 10:37 4楼

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

院士
2019-02-11 09:57 5楼

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

院士
2019-02-14 09:06 6楼

学习学习,谢谢分享!!

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

现在都不知道写什么啊

专家
2019-02-14 15:16 8楼

顶一个。。

工程师
2019-02-27 17:42 9楼
在void int0()interrupt 0 void int1()interrupt 1中怎么都是EX0 INT0中断允许。 EX1 INT1中断允许不用么?
菜鸟
2019-03-01 09:33 10楼

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

共10条 1/1 1 跳转至

回复

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