#define KEY0_PORT PORTD #define KEY0_DDR DDRD #define KEY0_PIN PIND #define KEY0 PD0 #define KEY1_PORT PORTD #define KEY1_DDR DDRD #define KEY1_PIN PIND #define KEY1 PD1 #define KEY2_PORT PORTD #define KEY2_DDR DDRD #define KEY2_PIN PIND #define KEY2 PD2 #define KEY3_PORT PORTD #define KEY3_DDR DDRD #define KEY3_PIN PIND #define KEY3 PD3 #define KEY0_STATUS (BIT_STATUS(KEY0_PIN,KEY0)) #define KEY1_STATUS (BIT_STATUS(KEY1_PIN,KEY1)) #define KEY2_STATUS (BIT_STATUS(KEY2_PIN,KEY2)) #define KEY3_STATUS (BIT_STATUS(KEY3_PIN,KEY3)) #define KEY_SERIES_FLAG 200 //按键连发开始所需时间长度 #define KEY_SERIES_DELAY 5 //按键连发的时间间隔长度 //按键属性 #define KEY_DOWN 0xA0 #define KEY_LONG 0xB0 #define KEY_LIAN 0xC0 #define KEY_UP 0xD0 #define KEY_LONG 0xB0 #define KEY_LIAN 0xC0 #define KEY_UP 0xD0 #define NO_KEY 0x00 #define KEY0_DOWN 0X01 #define KEY1_DOWN 0X02 #define KEY2_DOWN 0X03 #define KEY3_DOWN 0X04 #define KEY0_PRESS (KEY_DOWN|KEY0_DOWN) #define KEY1_PRESS (KEY_DOWN|KEY1_DOWN) #define KEY2_PRESS (KEY_DOWN|KEY2_DOWN) #define KEY3_PRESS (KEY_DOWN|KEY3_DOWN) key.c文件一部分 static uchar Get_Key(void) { if (KEY0_STATUS==0) return KEY0_DOWN; if (KEY1_STATUS==0) return KEY1_DOWN; if (KEY2_STATUS==0) return KEY2_DOWN; if (KEY3_STATUS==0) return KEY3_DOWN; return NO_KEY; } uchar Key_Scan(void) { static uchar Key_State = 0; //按键状态 static uchar Key_Prev = 0; //上一次按键 static uchar Key_Delay = 0; //按键连发时间 static uchar Key_Series = FALSE; //标志连发开始 uchar Key_Press = NO_KEY; //按键值 uchar Key_Return = NO_KEY; //按键返回值 Key_Press = Get_Key(); switch (Key_State) { case 0://按键初始态00 if (Key_Press !=NO_KEY)//有按键按下 { Key_State = 1;//转到按键确认 Key_Prev = Key_Press;//保存按键状态 } break; case 1://按键确认态01 if ( Key_Press ==Key_Prev )//确认和上次按键相同 { Key_State = 2;//判断按键长按 //返回按键按下键值,按键按下就响应,如果想弹起来再响应 //可以在弹起来后再返回按键值 Key_Return = KEY_DOWN | Key_Prev; } else//按键抬起,是抖动,不响应按键 { Key_State = 0; } break; case 2://按键释放态10 if (Key_Press == NO_KEY )//按键释放了 { Key_State = 0; Key_Delay = 0; Key_Series = FALSE; Key_Return = KEY_UP | Key_Prev; //返回按键抬起值 break; } if ( Key_Press ==Key_Prev ) { Key_Delay++; if ((Key_Series==TRUE) && (Key_Delay>KEY_SERIES_DELAY)) { Key_Delay = 0; Key_Return = KEY_LIAN | Key_Press; //返回连发的值 Key_Prev = Key_Press; //记住上次的按键. break; } if (Key_Delay>KEY_SERIES_FLAG) { Key_Series = TRUE; Key_Delay = 0; Key_Return = KEY_LONG | Key_Prev; //返回长按后的值 break; } } default : break; } return Key_Return; }每10ms调用一次按键检测,根据Key_Return的值来判断按键的操作,用状态机省去传统按键的延时去抖,也不在在按键的死等待,对程序时间的利用有很大的帮助,根据按键返回的状态值,事件可以在按键按下响应,也可以在按键弹起来响应,也可以实现连发、长按等功能。
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』