说在前面的话:亲戚这可算走完了,不知道小伙伴们过年忙完没有啊?
说起按键,总会让人头疼,它似乎是一个非常玄学的东西;也是历年来蓝桥杯单片机比赛的一个重难点。
对于蓝桥杯开发板而言,按键分为矩阵按键和独立按键两种,矩阵按键比独立按键难自然不多说,而一般情况下省赛期间补考矩阵按键但是还是能难倒一大批人;其主要原因在于一个按键可以有不同的功能,如果想要增加难度的话比赛也可以出长短按键也说不定;总之按键这个东西想出难可以使整个题目瞬间上升一个难度,但是其归根结底无非是对IO口状态的读取,但是却能灵活的运用到各个地方,因此平常的多多练习是必不可少的。
好了,言归正传,对于独立按键与其它外设的结合,我总结了几种方法:
1、传统方案——软件消抖or松手检测
优点:可以大概实现按键消抖的效果
缺点:使用软件延时浪费CPU时间、而且长按不丢的话可能影响数码管显示
//松手检测一般实现方法
sbit key1=P3^0;
if(key1==0){
num++;
}while(!key1);
优点:按着不丢的时候数据不会一直增加(如果是题目有要求的话另当别论)
缺点:按着不丢的时候动态扫描数码管不正常显示
当然也有第三种写法,就是软件消抖和松手检测写在一起的写法,但是似乎都解决不了手一直按着的问题(要么数据一直快速自加、要么数码管不正常显示);
因此我自己想了一个办法,谈不上多好,但是可以有效的解决这个问题,至少在实现效果来说是可以的。
2、改进方案
//改进方法
sbit key1=P3^0;
if(key1==0){
delay_ms(5);
if(key1==0){
num++;
}
}while(!key1){display();}
没错,就是在原有while(!key1)的里面添加了display();也就是数码管显示的函数;这可能有点操作系统的思想(开玩笑的了,比不上),也就是说,按键按下的时候,while是一直在循环的,也就是说CPU算是一直干等着,什么也没有干,因此你的动态扫描数码管显示当然无法正常显示了,所以基于这个的缺陷,while里面不能干等;在等的同时也要维持数码管的显示,这就保证了按下不丢的时候你的显示效果不受影响,说不定验分的时候这个实现效果也是一个添分项 你说是不是。。。但是,要知道,仅仅是维持数码管的显示,数据当然也就停止了(外设犹如DS1302什么的不会受影响的了~)
至于矩阵按键也是同样的道理,以下是矩阵按键的程序(直接复制我当年写的吧),谈不上多好,但是可以用。。
3、矩阵按键
其实对于矩阵按键,网上的方法层出不穷,有心的话一搜就能搜出一大堆教程+例程,所以我也在此不多费**,比较我也是用的人家的方法嘛。。。
unsigned char keyscan(){
unsigned char key_value;
unsigned char key_num;
P3=0x7f;
P44=0;P42=1;
key_value=P3;
key_value&=0x0f;
if(key_value!=0x0f){
key_value=P3;
switch(key_value){
case 0x7e:key_num=1;break;
case 0x7d:key_num=2;break;
case 0x7b:key_num=3;break;
case 0x77:key_num=4;break;
default:key_num=0x00;
}
}
//====================================
P3=0xbf;
P44=1;P42=0;
key_value=P3;
key_value&=0x0f;
if(key_value!=0x0f){
key_value=P3;
switch(key_value){
case 0xbe:key_num=5;break;
case 0xbd:key_num=6;break;
case 0xbb:key_num=7;break;
case 0xb7:key_num=8;break;
default:key_num=0x00;
}
}
//====================================
P3=0xdf;
P44=1;P42=1;
key_value=P3;
key_value&=0x0f;
if(key_value!=0x0f){
key_value=P3;
switch(key_value){
case 0xde:key_num=9;break;
case 0xdd:key_num=10;break;
case 0xdb:key_num=11;break;
case 0xd7:key_num=12;break;
default:key_num=0x00;
}
}
//====================================
P3=0xef;
P44=1;P42=1;
key_value=P3;
key_value&=0x0f;
if(key_value!=0x0f){
key_value=P3;
switch(key_value){
case 0xee:key_num=13;break;
case 0xed:key_num=14;break;
case 0xeb:key_num=15;break;
case 0xe7:key_num=16;break;
default:key_num=0x00;
}
}
return key_num;
}
采用的是比较传统的方式,如果想写成上方的改进版也是可以的,原理都是一样的;至于P44 和 P42 在完整电路分析的时候我似乎已经提到,它们分别代替了传统单片机的P37 和 P36
那么今天的内容就到这里的,下次见。。。。
|