以前我使用按键消抖都是用的延时函数,延时个10-20ms,用软延时的方式比较简单,但是会极大浪费单片机的资源,并且延时的并不是很精确,所以使用定时器来代替软延时。
#include#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了。



