51单片机按键的三种设计分析,即含按键消抖使用状态机法与延时方法、按键的按下松开设计以及按键的长按短按设计

一、前言

    相信大家在学完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的知识就能设计出自己想要的按键啦!

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值