您的位置:首页 > 其它

多功能检测按键-3 按键扫描 单按 长按 多个按键 响应方式

2014-05-23 10:34 274 查看
/***************************************
// 函数功能:按键扫描
//这是我第三次对按键扫描的优化,为什么我要这么做呢,很简单,
//我只想将简单的事情不断完善好
//第一次发表: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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: