哈喽哈喽大家好,我是阿飞的小蝴蝶,大家可以叫我阿飞或者小飞,我又回来啦,嘻~
昨天呢,我们详细的讲解了一下有关外部中断的基础知识,这部分知识老师上课时也有讲过,再加上昨天的复习内容,相信大家都能熟练的掌握了吧,好的,话不多说,直接来看一下我们昨天留下的那两个小练习:
1、使用外部中断0,通过按键S5来控制流水灯的方向(初始为 P1^0 -> P1^7,按下按键时改为P1^7 -> P1^0,再次按下时改为P1^0 -> P1^7... )
#include "stc15f2k60s2.h" #define u8 unsigned char #define u16 unsigned int bit mode=1; void HC138(u8 i) { switch(i) { case 4: P2 = (P2 & 0x1f) | 0x80; break; case 5: P2 = (P2 & 0x1f) | 0xa0; break; case 6: P2 = (P2 & 0x1f) | 0xc0; break; case 7: P2 = (P2 & 0x1f) | 0xe0; break; } } void delayms(u16 z) { u16 x,y; for(x=z;x>0;x--) for(y=845;y>0;y--); } void init_P0(void) { HC138(4); P0 = 0xff; HC138(5); P0 = 0x00; HC138(6); P0 = 0xff; HC138(7); P0 = 0xff; } void main() { u8 i; EA = 1; EX0 = 1; IT0 = 1; init_P0(); while(1) { HC138(4); P0 = ~(~(0xfe) << i); delayms(500); if(mode) { i++; if(i == 8) i = 0; } else { i--; if(i == 0xff) i = 7; } } } void int_0() interrupt 0 { EX0 = 0; mode = ~mode; EX0 = 1; }
现在来分析一下这段程序:(题目对应蓝桥杯应该是P0端口)
这段程序我们使用的是INT0,开头定义的变量“mode”是控制LED灯移动方向的标志位,因为程序中只需要两个方向的切换,所以这个标志位只需要一位(0和1)就可以控制,所以我们为了节省存储,把变量定义成了“bit”型变量,那么。。模式是怎么来切换的呢?我们来看主函数循环中那个判断语句:当“mode = 1”时,流水灯的方向为从P0^0~P0^7,当”mode == 0“时,流水灯的方向为从P0^7~P0^0,所以我们只要在触发中断的时候改变一下mode的值就可以了。
在主函数中,除了一些初始化以外,就只写了流水灯和mode对应的流水灯方向的程序,在程序最后边的中断处理函数中来改变mode的取值,这样一来,当我们按下按键S5时就会触发中断,流水灯的方向就会发生改变。(这里写的时候存在了一个问题,还是有关于按键抖动的,这个问题大家思考一下,可以把这段程序自己修改一下)
也许有的同学会问,写这个程序明明使用独立按键就可以了,为什么非要使用中断呢?大家仔细思考一下,这个程序单单使用机械按键真的可以吗?我们都知道,机械按键在使用的时候是需要程序一直扫描的,而在流水灯的程序中,我们是加了延时函数的,在执行延时函数时,程序会停在这个地方,这时候就没有办法扫描按键,即使我们按下了按键,程序也判断不到,所以这个时候我们就需要用到中断,即使是程序停在了延时函数这个地方,当触发了中断时,程序仍然会去执行中断处理函数中的程序,我们的按键也就能被检测到啦。
好的,接下来我们看下一个练习:
2、数码管任意一位显示数字0,通过LED灯来触发外部中断,让任意LED灯以一定间隔闪烁,每当灯亮起来的时候数码管显示的数字加1
#include "stc15f2k60s2.h" #define u8 unsigned char #define u16 unsigned int u8 code smgdu[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; u8 shuzhi; void HC138(u8 i) { switch(i) { case 4: P2 = (P2 & 0x1f) | 0x80; break; case 5: P2 = (P2 & 0x1f) | 0xa0; break; case 6: P2 = (P2 & 0x1f) | 0xc0; break; case 7: P2 = (P2 & 0x1f) | 0xe0; break; } } void delayms(u16 z) { u16 x,y; for(x=z;x>0;x--) for(y=845;y>0;y--); } void init_P0(void) { HC138(4); P0 = 0xff; HC138(5); P0 = 0x00; HC138(6); P0 = 0xff; HC138(7); P0 = 0xff; } void main() { EA = 1; EX1 = 1; IT1 = 1; init_P0(); HC138(6); P0 = 0x80; while(1) { HC138(4); P0 = 0x00; delayms(700); HC138(4); P0 = 0xff; delayms(700); } } void int_1() interrupt 2 { EX1 = 0; shuzhi++; if(shuzhi == 10) shuzhi = 0; HC138(7); P0 = smgdu[shuzhi]; EX1 = 1; }
还是直接来分析一下这段程序:
这段程序中使用的是INT1,我们可以看到,主函数中只写了些初始化程序和LED灯闪烁的程序,这题中我们需要用LED灯的闪烁来触发中断,当LED灯点亮时需要把IO口配置成低电平,熄灭时配置成高电平,这样一来LED灯的闪烁就可以产生高低电平交错的方波,也就有了下降沿,只要把这个电平接到对应的中断输入口(P3^3引脚)就可以触发INT1啦,所以运行这个程序时需要用杜邦线把P0端口任意一个引脚与P3^3引脚接在一起就好啦,好的这段程序与上一个类型的,大家自己看一下吧,我就不再做太多介绍啦。
到现在为止外部中断部分的内容就讲完啦,明天开始我们下一节内容:定时计数器基础知识讲解,悄悄给大家透露一下:定时器的使用比外部中断跟重要哦,学会使用定时器后,很多程序写起来都会得心应手,大家是不是已经蠢蠢欲动了呢?
好啦,今天的内容到这里就结束啦,程序中有什么问题也欢迎大家指出来,预祝大家都能取得好成绩