/***************************************
// 函数功能:按键扫描
//这是我第三次对按键扫描的优化,为什么我要这么做呢,非常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)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;
}
}