在大学里面,学习到了单片机。我们在学习按键的时候,都是利用电平的变化进行判断按键是否执行操作。如图所示:
而实际中,由于按键的弹片接触的时候,并不是一接触就紧紧的闭合,它还存在一定的
抖动,尽管这个时间非常的短暂,但是对于我们执行时间以 us 为计算单位的微控制器来说,
它太漫长了。因而,实际的波形图应该如下面这幅示意图一样;
这无疑我们要软件程序上进行消抖,从而判断稳定的电平来进行是否为有效操作。如果不做消抖操作,就会出现误判的现象,导致达不到有效的效果。
那么我们在大学里面的教科书上,是这样表述的:
unsinged char KeyScan(void)
{
unsigned char KeyValue=0;
if(KEY_IO != 0xFF) //检测到有按键按下
{
DelayNms(20); //延时 20 毫秒
if(KEY_IO != 0xFF)//确认按键按下
{
switch(KEY_IO)
{
case 0xFE: KeyValue=1;break;
case 0xFD: KeyValue=2;break;
default : KeyValue=0;break;
}
}
}
return KeyValue;
}
在实际的系统中,一般是不允许这么样做的。为什么呢?首先,这里的 Delayms(20) , 让微控制器在这里白白等待了 20 ms 的时间,啥也没干,这是不可取的。所以我们要学会释放内存。不让单片机做无用功。
在这里我可以提供两种方法:
法1:(参考杨源鑫博主的)
//读取按键
uchar read_key()
{
static int Key_on_off = 0 ;//按键自锁变量
uchar num , temp ;
num = P2 ; ///将P2的值存在变量num中
num &= 0xf0 ; //将低四位清0
if(num != 0xf0)
{
if(Key_on_off == 0)
{
Key_on_off = 1 ;
switch(num)
{
//返回按键的编码
case 0xe0 : temp = 1 ; break ;
case 0xd0 : temp = 2 ; break ;
case 0xb0 : temp = 3 ; break ;
case 0x70 : temp = 4 ; break ;
}
}
}
else
Key_on_off = 0 ;
return temp ;
}
法2:按键在松手后有效,灵敏度高,消耗资源少,运行效率高
#include<reg52.h>
#include<intrins.h>
//独立键盘.无按键动作时其返回值 num_key=0,否则返回按键号 num_key
extern unsigned char keyboard_self()
{
unsigned char num_key=0;//按键号
unsigned char temp=0;//用于读取 P2 线上按键值
static unsigned char temp_code=0;//保存按键值
static unsigned char num_check=0;//低电平有效次数
static unsigned char key_flag=0;//按键有效标识
temp=P2&0xF0;//读取 P2 线数据
if(temp!=0xF0)//低电平判断
{
num_check++;
if(num_check==10)//连续 10 次(10ms)低电平有效,则认为按键有效
{
key_flag=1;//使能按键有效标识
temp_code=temp;//保存按键值
}
else//松手时判断
{
num_check=0;
if(key_flag==1)//按键有效
{
key_flag=0;
switch(temp_code)//读取按键号
{
case 0xE0: num_key=1;
break;
case 0xD0: num_key=2;
break;
case 0xB0: num_key=3;
break;
case 0x70: num_key=4;
break;
}
}
}
return(num_key);
}
多多学习,高手请绕道。