/*************************************** // 函数功能:按键扫描 //这是我第三次对按键扫描的优化,为什么我要这么做呢,很简单, //我只想将简单的事情不断完善好 //第一次发表:http://blog.csdn.net/chuangwu2009/article/details/9466715 //第一次发表:http://blog.csdn.net/chuangwu2009/article/details/18032195 *****************************************/ /* 按键响应方式我个人总结了下,一共有11种(包括无按键) 按键响应方式:1:单按键按下响应 2:单按键按下释放响应 3:多按键按下响应 其中按下相应有:1.1:按下马上响应 1.2:长按后马上响应 1.3:长按后一直响应(如:长按累加更改时间设置) 释放响应有: 2.1:短按释放响应 2.2长按释放响应 多按键按下响应有: 1.1 1.2 1.3 2.1 2.2四种组合按键响应方式 */ #define SETB0 (unsigned char)0x01 #define SETB1 (unsigned char)0x02 #define SETB2 (unsigned char)0x04 #define SETB3 (unsigned char)0x05 #define SETB4 (unsigned char)0x10 #define SETB5 (unsigned char)0x20 #define SETB6 (unsigned char)0x40 #define SETB7 (unsigned char)0x80 typedef union uFLG1{ uint8 Flg ; struct FLAG1{ uint8 Flg1 : 1; uint8 Flg2 : 1; uint8 Flg3 : 1; uint8 Flg4 : 1; uint8 Flg5 : 1; uint8 Flg6 : 1; uint8 Flg7 : 1; uint8 Flg8 : 1; }tFlg1; }uFlg1; uFlg1 F_KEY={0}; //位定义 #define f_onekey F_KEY.tFlg1.Flg1//有单按键按下标志 #define F_longonekey F_KEY.tFlg1.Flg2//长按标志 #define f_mulkey F_KEY.tFlg1.Flg3//多按键标志 #define F_longmulkey F_KEY.tFlg1.Flg4//有多按键按下标志 #define F_first F_KEY.tFlg1.Flg5//上电识别是否上电按下 开机初始化时 执行 F_first = 1; //按键响应模式 #define NONE_KEY (unsigned char)0//无效按键值-无按键 #define ONE_DOWN (unsigned char)1 //单个按键按下响应--(短按)按下马上响应 #define ONE_LONG_DOWN (unsigned char)2 //单个按键长按下响应--长按时间到后的(马上)响应 #define MUL_DOWN (unsigned char)3 //多个按键按下响应 #define MUL_LONG_DOWN (unsigned char)4 //多个按键长按下响应 #define ONE_UP (unsigned char)5 //单个按键释放响应 #define MUL_UP (unsigned char)6 //多个按键释放响应 #define ONE_LONG_UP (unsigned char)7 //单个按键长按后释放响应 #define MUL_LONG_UP (unsigned char)8 //多个按键长按后释放响应 #define ONE_AL_DOWN (unsigned char)9 //单按键长按之后的响应-长按后一直响应(如:长按累加更改时间设置) #define MUL_AL_DOWN (unsigned char)10 //多按键长按之后的响应 #define LongAndShortUpIsSame //长按和短按释放按键功能一样 //定义此宏意思是 在短按按键释放后 或者长按按键后 // 功能执行是一样的 即执行ONE_UP或者MUL_UP的动作 static uint8 key_value1=0;//单前按键值 //按键值寄存器-当前按下的值-按下马上响应一次动作 static uint8 key_value2=0; //按键值寄存器-前一次的值 //--长按响应一次动作或者按键短按释放响应一次动作 static uint8 key_value3=0; //按键值寄存器长按的值---长按后一直响应 static uint8 mode_key=0;//按键响应模式 void Key_scan(void) // { static uint8 key_delay=0;//按键去抖动寄存器 static uint8 key_value0=0;//前一次按键值寄存器 static uint8 key1_mult=0;//多按键寄存器2 static uint8 key_longtime=0;//长按时间累积寄存器1 static uint8 key_longtime1=0;//长按时间累积寄存器2 uint8 key_mult=0;//多按键寄存器1 if(!P_K0)// { key_value1|=SETB0; key_mult++; } if(!P_K1)// { key_value1|=SETB1; key_mult++; } /* if(!P_K2)// { key_value1|=SETB2; key_mult++; } if(!P_K3)// { key_value1|=SETB3; key_mult++; } if(!P_K4)// { key_value1|=SETB4; key_mult++; } */ if(key_value1 == key_value0)//如不响等,保存当前按键值,清抖动寄存器,以此次识别 { if(key_delay > 10)//抖动处理 { if(key_value1 > 0)//无按键按下确认,等于0时表示无按键 { if(1 == key_mult) {//单按键按下处理程序 if(!f_onekey) { //单按键短按按下处理程序 f_onekey=1; key1_mult=0; mode_key=ONE_DOWN; } else {//单按键长按 if(!F_longonekey) {//还没达到长按时间 if(++key_longtime>=100)// { key_longtime=0; if(++key_longtime1>=15) {//长按时间到 key_longtime1=0; mode_key=ONE_LONG_DOWN; F_longonekey=1; //长按按键处理程序 } } else {//还没达到长按时间 mode_key=NONE_KEY; } } else {//单按键长按之后的响应 mode_key = ONE_AL_DOWN; } } } else { //多按键按下处理程序 key1_mult=1; if(!f_mulkey) {//多按键短按下相应 f_mulkey=1; f_onekey=1; // f_onekey=1; 防止多个按键释放时候,不同时释放,响应单个按键功能 mode_key=MUL_DOWN; } else {//多按键长按 if(!F_longmulkey) { if(++key_longtime>=100)//2毫秒1次 100*2*15=3秒 { key_longtime=0; if(++key_longtime1>=15) { key_longtime1=0;//3秒时间到 F_longmulkey=1; //多按键长按按键处理程序 mode_key=MUL_LONG_DOWN; } } else { mode_key=NONE_KEY; } } else { //多按键长按之后的响应 mode_key = MUL_AL_DOWN; } } } } else//按键释放或者无按键 { f_mulkey=0; F_first=0; key_longtime=0; key_longtime1=0; if(F_longonekey) {//长按单按键释放 F_longonekey=0; #ifdef (LongAndShortUpIsSame) mode_key=ONE_UP; #else mode_key=ONE_LONG_UP; #endif } else if(F_longmulkey) {//长按多按键释放 F_longmulkey=0; #ifdef (LongAndShortUpIsSame) mode_key=MUL_UP; #else mode_key=MUL_LONG_UP; #endif } else if(f_onekey) {//短按按键释放 if(0==key1_mult) { mode_key=ONE_UP; } else { mode_key=MUL_UP; } } else { mode_key=NONE_KEY; } f_onekey=0; } } else {//滤波处理 key_delay++; } } else { key_value0=key_value1; key_delay=0; } } //************************************* // 函数名称:key_deal // 函数功能:按键响应后的处理 // 入口参数:无 // 出口参数:无 //***************************************/ void key_deal(void) { static uint8 key_longtime=0;//长按时间累积寄存器1 switch(mode_key) { case ONE_DOWN://单个按键按下响应 { switch(key_value1) { case SETB1://P_K1短按下响应 { key_value2 = key_value1; if(F_first) {//按住按键上电响应-要执行的动作-常用于自检 break; } break; } case SETB0:///P_K0短按下响应 { key_value2 = key_value1; if(F_first) { break; } break; } default: break; } key_value1 = 0; break; } case ONE_LONG_DOWN://单个按键长按下响应--相应一次 { key_value3=key_value2; switch(key_value2) { case SETB1: { break; } case SETB0: { break; } default: break; } key_value2=0; break; } case MUL_DOWN://多个按键按下响应 { switch(key_value1) { case (SETB1|SETB0): { key_value2 = key_value1; break; } default: break; } key_value1=0; break; } case MUL_LONG_DOWN://多个按键长按下响应 { if(key_value2==(SETB0|SETB1)) { key_value3=key_value2; } key_value2=0; break; } case ONE_UP://单个按键释放响应 { switch(key_value2) { case SETB0: {//TURBO释放 break; } case SETB1: { break; } default: break; } key_value2=0;//按键释放后清零 break; } case MUL_UP://多个按键释放响应 { key_value2=0;//按键释放后清零 key_value3=0; break; } case ONE_LONG_UP://单个按键长按后释放响应 { switch(key_value3) { case SETB0: {//TURBO释放 break; } case SETB1: { break; } default: break; } key_value2=0;// key_value3=0; break; } case MUL_LONG_UP://多个按键长按后释放响应 { key_value2=0;//按键释放后清零 key_value3=0; break; } case ONE_AL_DOWN://单按键长按之后的响应 { if(++key_longtime>=100)//2毫秒1次 40*15*5=3秒 { key_longtime=0; switch(key_value3) { case SETB0: { break; } case SETB1: { break; } default: break; } } break; } case MUL_AL_DOWN://多按键长按之后的响应 { if(++key_longtime>=100)//2毫秒1次 40*15*5=3秒 { key_longtime=0; } break; } default: break; } }
多功能检测按键-3 单按 长按 多个按键 响应方式,布布扣,bubuko.com
原文地址:http://blog.csdn.net/chuangwu2009/article/details/26679005