以前我使用按键消抖都是用的延时函数,延时个10-20ms,用软延时的方式比较简单,但是会极大浪费单片机的资源,并且延时的并不是很精确,所以使用定时器来代替软延时。
#include <reg51.h>
#define NoKeyProcess 0
#define Key1_Press 1
#define Key2_Press 2
#define Key3_Press 3
#define Key4_Press 4
void Key()
{
sbit key1 = P3^1; //1号病床输入
sbit key2 = P3^0; //2号病床输入
sbit key3 = P3^2; //3号病床输入
sbit key4 = P3^3; //4号病床输入
static unsigned char Key_status = 0,priv_key_val = 0;
unsigned char Key_Value = 0;
Key_Value|=(key1==1)? NoKeyProcess:Key1_Press; //如果按键按下了(括号内值为假),Key_Value = 1.
Key_Value|=(key2==1)? NoKeyProcess:Key2_Press; //如果按键按下了(括号内值为假),Key_Value = 2.
Key_Value|=(key3==1)? NoKeyProcess:Key3_Press; //如果按键按下了(括号内值为假),Key_Value = 3.
Key_Value|=(key4==1)? NoKeyProcess:Key4_Press; //如果按键按下了(括号内值为假),Key_Value = 4.
switch(Key_status)
{
case 0: //Key pressed
if(Key_Value)
{
priv_key_val=Key_Value;
Key_status++;
}
break;
case 1: //Confirm key pressed
if(priv_key_val==Key_Value)
{
Key_status++;
}
else
Key_status=0;
break;
case 2:// Wait to release
if(Key_Value !=priv_key_val)
{
Key_status = 0;
Key_Process(priv_key_val); //按键处理函数
}
break;
default:break;
}
}
void Timer0_ISR() interrupt 1 //TIM0 中断服务函数
{
TH0=T0RH;
TL0=T0RL;
vKey_Scan();
}
注释:如果病床1号按下按键,Key_Value的值就为 1,然后进入switch的case0,因为Key_Value的值为真,所以进入if把值赋给priv_key_val,然后等下次进入switch,也就是10ms后再次进入Key函数,此时1号病床的按键还是按下的,因为人体按按键最快的时间大概是100ms之后,所以第二次来到case1,这里是确认了按键确实按下了,而不是因为抖动,并且还判断这次按下的键是不是还是按键1,如果是,就等下个10ms进入case2,如果不是同一个按键按下了就退回到case0,case2是检测按键是否释放,如果是,就将Key_status = 0方便下次按键判断然后执行那件处理函数。。。
当没有按键按下时,Key_Value值就为0,就进不去case1了。