关于51单片机的按键操作总结(状态机)

在大学里面,学习到了单片机。我们在学习按键的时候,都是利用电平的变化进行判断按键是否执行操作。如图所示:

关于51单片机的按键操作总结(状态机)_第1张图片

 

而实际中,由于按键的弹片接触的时候,并不是一接触就紧紧的闭合,它还存在一定的
抖动,尽管这个时间非常的短暂,但是对于我们执行时间以 us 为计算单位的微控制器来说,

它太漫长了。因而,实际的波形图应该如下面这幅示意图一样;

关于51单片机的按键操作总结(状态机)_第2张图片

这无疑我们要软件程序上进行消抖,从而判断稳定的电平来进行是否为有效操作。如果不做消抖操作,就会出现误判的现象,导致达不到有效的效果。

那么我们在大学里面的教科书上,是这样表述的:

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
#include
//独立键盘.无按键动作时其返回值 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);
}

 

多多学习,高手请绕道。

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