/***************************************// 函数功能:按键扫描//这是我第三次对按键扫描的优化,为什么我要这么做呢,非常easy,//我仅仅想将简单的事情不断完好好//第一次发表: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)0x80typedef 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; }}