51单片机外设之——按键的检测(快速识别)

前面提到的按键的检测,第一种传统的扫描存在延时消抖和while松手检测语句的缺点;第二种的带标志位的检测法存在延时消抖的缺点;而现在介绍的按键扫描法是“快速识别”方法(以独立按键为例,因为矩阵键盘的扫描与独立按键类似)。
首先附上按键的原理图:
51单片机外设之——按键的检测(快速识别)_第1张图片
用跳帽连接排针 J5 的2脚与3脚,将键盘设置为独立按键(只有S4~S7有效)。此时,S4~S7一端分别与P3^3~P3^0相连,另一端连向GND。

其核心代码如下,以按下 S4 为例:

uchar key_now = 1;                         //用处存储按键本次的状态(0表示按下,1表示未按下)
uchar key_flag = 0;                        //按键是否按下的标志(0表示按键未被按下,1表示按键被按下)
uchar key_old = 1;                         //用于存储按键上次的状态(0表示上次按下,1表示上次未按下)
sbit s4 = P3^3;
void key_scan()
{
    key_now = s4;
    key_flag = (key_now ^ key_old) ^ key_flag;
    key_old = key_now;
}

符号“^”为“异或”的计算机语言。
其代码的思路如下,以下的“=”表示“等于”,而不是“赋值”:
首先,把三个标志位置初始化(key_now = key_old = 1,key_flag = 0)。因为,当没有按键按下时,key_now 等于 s4(P3^3)的电平值(为1);
key_flag = (1 ^ 1) ^ 0 = 0;key_old = key_now = 1,这与初始化状态相同。
其次,当有键按下时,key_now = s4(P3^3) = 0;key_flag = (0 ^ 1) ^ 0 = 1;key_old = key_now = 0;这时,key_flag = 1,代表是有按键按下。若此后按键未释放(P3^3一直保持低电平),则 key_now = 0; key_flag = (0 ^ 0) ^ 1 = 1;key_old = key_now = 0;仍与按下的结果相同。若按键释放后,key_now = 1(P3^3);key_flag = (1 ^ 0) ^ 1 = 0;key_old = key_now = 1;此时key_flag = 0,表示按键已经释放,其结果与初始化相同,也就是与按键未按下时的结果相同。
最后,我们只需要判断 key_flag 是否长时间为“1”,即可判断按键是否按下。
上述的方式中,若对于无效按键(或者是按键按下时的抖动部分),处理的方法是,预估出一个数值Num,对于key_flag = 1的次数进行计数,当key_flag = 1的次数大于或等于预估值时,则判断为有效按键。而对于这个预估值,只是让它避免按键为抖动或者无效的情况,对于这个数跟据程序的情况,是不难处理的。
此法的优点在于,没有delay10ms()的延时部分,即便是在计算key_flag = 1 的次数时,程序也可以进行其他的处理,不需要总是卡在delay的延时函数中。
综上,对于按键的处理的三种主要的方法已经罗列,剩下的还有外部中断对按键的检测(这个方法一般很少用到。因为中断的资源是比较宝贵的,而且这个方法也不简单,后面谈到中断时,会进行阐述)。
其实以上三种方法并没有特别的好坏之分,按照程序的情况再加以应用即可!

未完待续……

你可能感兴趣的:(51单片机)