一、前言
相信大家在学完51单片机后,大家都想了解单片机按键的直接按下、按下与松开等转态的设计。下面小编就带大家来了解一下51单片机按键的各种玩儿法吧!
二、获取按键键值
按键设计函数
#define kbd_io P3
#define kbd_maskrow 0x0f
unsigned char scankbd(){
unsigned char key_num1 = 0;
unsigned char kbd_press;
static unsigned char kbd_state = 0;
switch(kbd_state){
case 0:
kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io;
if(kbd_press != kbd_maskrow){
kbd_state = 1;
}
break;
case 1:
kbd_press = kbd_io;
if(kbd_press != kbd_maskrow){
if((kbd_io&0x08)==0) key_num1 = 0;
if((kbd_io&0x04)==0) key_num1 = 1;
if((kbd_io&0x02)==0) key_num1 = 2;
if((kbd_io&0x01)==0) key_num1 = 3;
kbd_io = 0xf0;P44 = 1;P42 = 1;
if(P44 == 0) key_num1 += 0;
if(P42 == 0) key_num1 += 4;
if((kbd_io&0x20)==0) key_num1 += 8;
if((kbd_io&0x10)==0) key_num1 += 12;
kbd_state = 2;
}else{
kbd_state = 0;
}
break;
case 2:
kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io;
if(kbd_press == kbd_maskrow){
kbd_state = 0;
}
break;
}
return key_num1;
}
设计思路 1.在状态1中,首先,判断按键是否按下,按下则准备跳转到状态2;否则,就在状态1等待; 2.在状态2中,再次,判断按键是否按下,没有按下则回到状态1;否则,就判断具体按下按键的值,并且准备跳转到状态3; 3.在状态3中,判断按键是否松开,若没有松开则还是停留状态3;否则,就返回到状态1;
三、按键的按下与松开
按键设计函数
unsigned char key_read(){
unsigned int key_new;
unsigned char key_val;
P44 = 0;P42 = 1;P35 = 1;P34 = 1;
key_new = P3;
P44 = 1;P42 = 0;
key_new = (key_new<<4)|(P3&0x0f);
P42 = 1;P35 = 0;
key_new = (key_new<<4)|(P3&0x0f);
P35 = 1;P34 = 0;
key_new = (key_new<<4)|(P3&0x0f);
switch(~key_new){
case 0x8000: key_val = 4;break;
case 0x4000: key_val = 5;break;
case 0x2000: key_val = 6;break;
case 0x1000: key_val = 7;break;
case 0x0800: key_val = 8;break;
case 0x0400: key_val = 9;break;
case 0x0200: key_val = 10;break;
case 0x0100: key_val = 11;break;
case 0x0080: key_val = 12;break;
case 0x0040: key_val = 13;break;
case 0x0020: key_val = 14;break;
case 0x0010: key_val = 15;break;
case 0x0008: key_val = 16;break;
case 0x0004: key_val = 17;break;
case 0x0002: key_val = 18;break;
case 0x0001: key_val = 19;break;
default:key_val = 0;break;
}
return key_val;
}
使用示例:
key_num = key_read();//获取按键的值
key_down = key_num & (key_old ^ key_num);//获取按键是否按下
key_up = ~key_num & (key_old ^ key_num);//获取按键是否松开
key_old = key_num;//保存本次按键的值
设计思路 1.获取按键的值; 2.通过本次按键值跟上次按键的值进行与、异或运算得到按键按下与松开的状态; 3.保存本次按键的值;
四、按键的长按与短按
按键设计函数
unsigned char key_read(){
unsigned int key_new;
unsigned char key_val;
P44 = 0;P42 = 1;P35 = 1;P34 = 1;
key_new = P3;
P44 = 1;P42 = 0;
key_new = (key_new<<4)|(P3&0x0f);
P42 = 1;P35 = 0;
key_new = (key_new<<4)|(P3&0x0f);
P35 = 1;P34 = 0;
key_new = (key_new<<4)|(P3&0x0f);
switch(~key_new){
case 0x8000: key_val = 4;break;
case 0x4000: key_val = 5;break;
case 0x2000: key_val = 6;break;
case 0x1000: key_val = 7;break;
case 0x0800: key_val = 8;break;
case 0x0400: key_val = 9;break;
case 0x0200: key_val = 10;break;
case 0x0100: key_val = 11;break;
case 0x0080: key_val = 12;break;
case 0x0040: key_val = 13;break;
case 0x0020: key_val = 14;break;
case 0x0010: key_val = 15;break;
case 0x0008: key_val = 16;break;
case 0x0004: key_val = 17;break;
case 0x0002: key_val = 18;break;
case 0x0001: key_val = 19;break;
default:key_val = 0;break;
}
return key_val;
}
中断计时函数
void time1() interrupt 3{//中断服务函数
key_num = key_read();
if(key_num == key_old){
key_count++;
}else{
key_count=0;
}
key_old = key_num;
}
使用示例
if(key_num == 4 && key_count>=800)//长按800毫秒设计
segbuff[0] = 0;
if(key_num == 5)//短按设计
segbuff[0] = 1;
if(key_num == 8 && key_count>=400)//长按400毫秒设计
segbuff[0] = 2;
设计思路 1.获取按键的值; 2.判断按键的值与上一次按键的值是否相等,相等则计时开始;不相等则计时为0,等待计时;
五、总结
为了是大家能够更好的理解长按短按、按下与松开、普通按键之间的区别,小编建议大家直接采用后面两个的设计函数,这样子能够更好的切合按键各种状态,也能够帮助自己更好的理解。但是第一种设计函数也并不是不能够实现后面两种需求,只是小编忘记具体的设计代码了。 总的来说,设计各种按键还是比较简单的,只要明白自己的需求,再加上自己一些51的知识就能设计出自己想要的按键啦!