1.缺陷
上一讲讲解的“不支持连按”模式贴合了我们在生活中的实际应用,虽然我们仅用“while(KEY4==0);”就把按键模式给切换了,不过这条语句严格来说是有缺陷的。
现在我们编写的都是简单的程序,如果后面还有更多更复杂的程序时,“while(KEY4==0);”就成为BUG了。
如果我们对按键按下不松手,那程序就一直在循环等待,不遇到高电平就不往下执行代码,如果这时有重要的程序要执行,那岂不是因按键而耽误。
还有我们再看下面这些代码
while(1) { if(KEY4==0) { delay_ms(10);//等待抖动过去 if(KEY4==0) //二次判断 { //这里执行某些功能语句 } } }
即使我们不使用“while(KEY4==0);”,只要我们按键不松手,每次都要执行“delay_ms(10);”,这样的代码称不上高效率,我们只能再次完善代码了。
2.改善
首先我们为了让程序做到通用性,我们定义一个key_up为unsigned char类型的变量,而不是像宋老师那样在《手把手教你学51单片机》文档8.4.3节后面的文字内容说到的利用bit类型的变量,毕竟bit类型只适合在51单片机,要是移植到其他单片机里就不适用了,所以我们不打算使用这种变量。
我们新定义的key_up变量是用来记录此时按键IO端口的扫描值,进一步分析,当按键按下不松手时,
此时的key_up等于KEY4(也就是0),当按键松手后,key_up就等于1了。
然后想进入执行功能语句时,先过了“if(key_up==0)”这一关,因为我们一直让key_up在死循环里存取KEY4的值,所以只要没有按键动作,key_up一直等于1,这样连进入功能语句的第一关都没有资格。
当有按键按下时,key_up等于0了,进入了第一关,然后我们再设最后一关,如果通过了最后一关就可以执行功能语句了,最后一关是判断“if(KEY4==1)”,也就是说如果按键没松手,就无法执行功能语句了。没错,我们这次的不支持连按模式是只有按键松手之后才去执行的,上一讲则是按下之后过了10ms就执行代码了。
3.代码
#include <reg52.h> sbit ADDR2 = P1^2; sbit ADDR1 = P1^1; sbit ADDR0 = P1^0; sbit ENLED = P1^4; sbit ADDR3 = P1^3; sbit LED2 = P0^0; sbit KEY4 = P2^7; void delay_ms(unsigned int x) { unsigned int i,j; if(x==1000) { for(i=0;i<19601;i++)//延时1s { for(j=5;j>0;j--); } } else while(x--)for(j=115;j>0;j--); } void main() { unsigned char key_up=1;//定义记录按键状态值的变量,初始值为1避免程序一开始就进入了“if(key_up==0)” unsigned char i=1; ADDR3 = 1;//使能三八译码器 ENLED = 0;// ADDR2 = 1;//************************** ADDR1 = 1;//让三八译码器的IO6输出低电平 ADDR0 = 0;//************************** P2 = 0xF7;//让K4能具备有被拉低的条件先 P0 = 0xFE;//先点亮LED2 while(1) { if(key_up==0) { if(KEY4==1)//只要不松手,KEY4就会等于0,只有在按键抬起之后才执行功能代码 { P0=~(0x01<<i); i++; if(i>=8)i=0; } } key_up=KEY4; //如果不松手,key_up就会等于0 delay_ms(2); //假设这部分是要执行的其他程序 } }
大家可以照着代码分析一下,我们是不是已经解决了上一讲代码的两处缺陷。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程