0000 0110 & 0000 0100=0000 0100
(所以与本次扫描的键值与,可以得到首次按下的键值)
KEY_DOWN=(KEY_LAST^KEY_PRESS) & KEY_PRESS; //按下的键值
4.2弹起的键值,与按下的原理一样,不同的是要和上次扫描的键值相与
如 0000 0010表示上次扫描的键,第1位是按下的状态
0000 0100 表示本次扫描的键,第2位是按下的,
我们要算出第1位是弹起,则
0000 0010 ^ 0000 0100=0000 0110
0000 0110 & 0000 0010=0000 0010
KEY_UP=(KEY_LAST^KEY_PRESS) & KEY_LAST;//弹起的键值(包含长按键)
4.3长按键一般单独处理,弹起时如果要排除,避免多次触发事件,需要计算出
不包含长按键的键值,用如下公式
KEY_UP_NL=(~KEY_LONG) & KEY_UP; //弹起的键值(不包含长按键)
4.4 长按键的计算逻辑,见程序注释
5、如何使用
5.1 设置好长按的时间
#define longkey_times 2000 //这里表示2秒
5.2 修改扫描键值
TEMP_KEY = PIND & 0x0C; //批量扫描IO,并生成键值,用户需结合项目自已修改,PIND
//此处表示PD0-7的端口,不同单片机不一样,0x0C只取出 PD2 PD3的值
TEMP_KEY ^= 0x0C; //此处主要是把键值取反,如果你的按键是低电平触发的话
//还有一处地方也要一起改
KEY_PRESS = PIND & 0x0C;
KEY_PRESS ^= 0x0C;
注意:51或其他单片机中,如果按键不在同一序列,比如P01 P03 P14 P16,则可以如下设置
TEMP_KEY = P0 & 0x0A; //取出 P01 P03
TEMP_KEY |=(P1 & 0x50); //取出 P14 P16
TEMP_KEY ^= (0x0A|0x50); //此处主要是把键值取反,如果你的按键是低电平触发的话,
//如果你的按键是高电平触发,则删除此行,不需要取反
//还有一处地方也要一起改
KEY_PRESS = P0 & 0x0A; //取出 P01 P03
KEY_PRESS |=(P1 & 0x50); //取出 P14 P16
KEY_PRESS ^= (0x0A|0x50); //此处主要是把键值取反,如果你的按键是低电平触发的话,
//如果你的按键是高电平触发,则删除此行,不需要取反
为了编程方便,尽量使用同一序列的口,如果不同序列的口,那端口号也要能错开,如用了P01,就不要用P11了。
这样的话,才能方便计算,提高扫描效率,如果非要用,只能通过移位处理
如51或其他单片机中,想判断 P01 P02 P12 P13的键
TEMP_KEY = P1 & 0x0C; //取出 P12 P13
TEMP_KEY =TEMP_KEY<<1; //左移1位,避开P12和P02交叉重叠