|
发表于 2010-9-20 15:26:51
|
显示全部楼层
我也来一个数据与过程分离的按键函数吧
#include "Global.h"
_CONST_ROM_ KEY_PARAM c_aKeyParam_Tab[] =
{//按键消息,按键长短按功能都在这里填上去就可以了
{KEY_NUM0, LONG_PRESS_NONE},
{KEY_NUM1, LONG_PRESS_NONE},
{KEY_NUM2, LONG_PRESS_NONE},
{KEY_NUM3, LONG_PRESS_NONE},
{KEY_NUM4, LONG_PRESS_NONE},
{KEY_NUM5, LONG_PRESS_NONE},
{KEY_NUM6, LONG_PRESS_NONE},
{KEY_NUM7, LONG_PRESS_NONE},
{KEY_NUM8, LONG_PRESS_NONE},
{KEY_NUM9, LONG_PRESS_NONE},
{KEY_POWER, LONG_PRESS_NONE},
{KEY_VOLUP, LONG_PRESS_HOLD_SHORT},
{KEY_VOLDN, LONG_PRESS_HOLD_SHORT},
{KEY_UP, LONG_PRESS_NONE},
{KEY_DOWN, LONG_PRESS_NONE},
{KEY_LEFT, LONG_PRESS_NONE},
{KEY_RIGHT, LONG_PRESS_NONE},
{KEY_ENTER, LONG_PRESS_NONE},
{KEY_EXIT, LONG_PRESS_NONE},
};
UINT8 Get_Max_Key(void)
{
return (sizeof(c_aKeyParam_Tab)/sizeof(KEY_PARAM));
}
void Key_Init(void)//该函数初始化调用即可
{
Clr_Key();
#ifdef SUPPORT_ADC
ADC_Init();
#endif
}
void Key_Proc(void)//此函数放在主循环处一直调用
{
UINT16 m_uiKeyCodeHead;
ADC_Read_Proc();//ad值获取(如果用矩阵或独立按键就不需要此函数)
Key_Scan(Get_AdKeyCode());//按键扫描(Get_AdKeyCode()是ad处理得出来的按键消息)
//Key_Scan是处理按键的过程,Get_AdKeyCode是处理按键的数据
m_uiKeyCodeHead = Get_Msg_Type();
if((m_uiKeyCodeHead != MSG_KEY)&&(m_uiKeyCodeHead != MSG_IR))
{
Clr_Key();
return;//没有按键或遥控消息退出
}
Comm_Key_Proc();//按键功能处理用这个函数
Clr_Key();
}
#ifndef __KEY_H__
#define __KEY_H__
enum {//按键消息枚举
KEY_ERR = 0,
KEY_POWER,
KEY_VOLUP,
KEY_VOLDN,
KEY_NUM0,
KEY_NUM1,
KEY_NUM2,
KEY_NUM3,
KEY_NUM4,
KEY_NUM5,
KEY_NUM6,
KEY_NUM7,
KEY_NUM8,
KEY_NUM9,
KEY_UP,
KEY_DOWN,
KEY_LEFT,
KEY_RIGHT,
KEY_ENTER,
KEY_EXIT,
/* Max Key 0xfe */
KEY_NULL = 0xff,
};
extern _CONST_ROM_ KEY_PARAM c_aKeyParam_Tab[];
extern UINT8 Get_Max_Key(void);
extern void Key_Init(void);
extern void Key_Proc(void);
#endif
#include "Global.h"
KEY_INFO g_KeyInfo = {KEY_NULL,0,0,0,0,LONG_PRESS_NONE};//按键扫描结构体
UINT16 g_uiKeyCode;//这个是全局按键消息变量
void Key_Scan(UINT8 m_ucKeyCode)//按键扫描,这个也是数据与过程分离的
{
UINT8 m_ucKeyIndex;
if(m_ucKeyCode == KEY_NULL)
{
if(KEY_NULL == g_KeyInfo.Val) //没有按键按下
{
return;
}
if((g_KeyInfo.Interval >= TICK_STILL_PRESSED_STEP)
//&&(g_KeyInfo.Duration < TICK_TH_SHORT_PRESS))
&&(g_KeyInfo.Duration < TICK_TH_LONG_PRESS))//按键已经释放
{
if((g_KeyInfo.Status != (PRESS_KEY_DOWN|KEY_TIME_LONG)>>8)
&&((g_KeyInfo.KeyHoldPeriod == LONG_PRESS_ONCE)
||(g_KeyInfo.KeyHoldPeriod == LONG_PRESS_HOLD_LONG)
||(g_KeyInfo.KeyHoldPeriod == LONG_PRESS_HOLD_SHORT))
)
{
g_KeyInfo.Val &= KEY_VAL;
g_KeyInfo.Status = (PRESS_KEY_UP|KEY_TIME_SHORT)>>8;
g_uiKeyCode = MSG_KEY|(g_KeyInfo.Status<<8)|g_KeyInfo.Val;
}
}
g_KeyInfo.Val = KEY_NULL;
g_KeyInfo.Status = 0;
g_KeyInfo.Duration = 0;
g_KeyInfo.Interval = 0;
Set_Key_Release();
return;
}
if(m_ucKeyCode == g_KeyInfo.Val)//相同按键按下
{
if(If_Key_Process_Once())//如果该按键没有长按功能就退出
return;
if(F_KEY_SCAN_KICK)//F_Sys_2msec_kick 是定时器2ms定时标志
{
F_KEY_SCAN_KICK = 0;
g_KeyInfo.Duration++;
g_KeyInfo.Interval++;
}
if(g_KeyInfo.Interval >= TICK_STILL_PRESSED_STEP)//消抖判断
{
if((g_KeyInfo.Duration > TICK_TH_LONG_PRESS)
&&(g_KeyInfo.Duration < TICK_TH_STILL_PRESS))//是长按
{
if(g_KeyInfo.KeyHoldPeriod == LONG_PRESS_ONCE)
{
Set_Key_Process_Once();//当前按键没有长按功能
}
else
{
Set_Key_Process_Continue();//当前按键有长按功能
}
g_KeyInfo.Duration = g_KeyInfo.KeyHoldPeriod;
g_KeyInfo.Interval = 0;
g_KeyInfo.Val &= KEY_VAL;
g_KeyInfo.Status = (PRESS_KEY_DOWN|KEY_TIME_LONG)>>8;
g_uiKeyCode = MSG_KEY|(g_KeyInfo.Status<<8)|g_KeyInfo.Val;//发送长按消息
}
else//是短按
{
if(g_KeyInfo.KeyHoldPeriod == LONG_PRESS_NONE)
{
g_KeyInfo.Duration = g_KeyInfo.KeyHoldPeriod;
g_KeyInfo.Interval = 0;
g_KeyInfo.Val &= KEY_VAL;
g_KeyInfo.Status = (PRESS_KEY_DOWN|KEY_TIME_SHORT)>>8;
g_uiKeyCode = MSG_KEY|(g_KeyInfo.Status<<8)|g_KeyInfo.Val;//发送短按消息
Set_Key_Process_Once();
}
}
}
}
else//发现有按键按下
{
Set_Key_Release();
g_KeyInfo.Val = m_ucKeyCode;
g_KeyInfo.Status = 0;
g_KeyInfo.Duration = 0;
g_KeyInfo.Interval = 0;
g_KeyInfo.KeyHoldPeriod = LONG_PRESS_NONE;
for(m_ucKeyIndex=0;m_ucKeyIndex<Get_Max_Key();m_ucKeyIndex++)
{
if(c_aKeyParam_Tab[m_ucKeyIndex].KeyCodeIdx == g_KeyInfo.Val)//查找是哪一个按键
{
g_KeyInfo.KeyHoldPeriod = c_aKeyParam_Tab[m_ucKeyIndex].LongKeyPeriod;//获取按键是否支持长按功能
break;
}
}
}
}
#ifndef __KEY_SCAN_H__
#define __KEY_SCAN_H__
#define MSG_TYPE 0xf000//消息类型,按键,遥控等
#define MSG_ATTR 0x0f00//长按,短按,按键按下,按键弹起
#define MSG_NULL 0xffff// 空消息
#define MSG_KEY 0x1000// 按键消息
#define MSG_IR 0x2000//红外消息
#define PRESS_KEY_DOWN (0<<9)//0x00 //按下时触发
#define PRESS_KEY_UP (1<<9)//弹起时触发
#define KEY_TIME_SHORT (0<<8)//0x00 //短按
#define KEY_TIME_LONG (1<<8)//长按
#define KEY_TIME (1<<8)
#define KEY_VAL 0xff
#define Get_Msg_Type() (g_uiKeyCode&MSG_TYPE)
#define Get_Key_Val() (g_uiKeyCode&KEY_VAL)
#define If_Key_Time_Short() ((g_uiKeyCode&MSG_ATTR) == KEY_TIME_SHORT)
#define If_Key_Time_Long() ((g_uiKeyCode&MSG_ATTR) == KEY_TIME_LONG)
#define Clr_Key() (g_uiKeyCode = MSG_NULL)
#define Get_Key() (g_uiKeyCode&(KEY_TIME|KEY_VAL))
#define TICK_MSEC10 5//该值根据需要调整(F_KEY_SCAN_KICK*5ms)
#define TICK_MSEC20 TICK_MSEC10*2
#define TICK_MSEC30 TICK_MSEC10*3
#define TICK_MSEC40 TICK_MSEC10*4
#define TICK_MSEC50 TICK_MSEC10*5
#define TICK_MSEC60 TICK_MSEC10*6
#define TICK_MSEC100 TICK_MSEC10*10
#define TICK_MSEC200 TICK_MSEC10*20
#define TICK_MSEC300 TICK_MSEC10*30
#define TICK_MSEC400 TICK_MSEC10*40
#define TICK_MSEC500 TICK_MSEC10*50
#define TICK_MSEC600 TICK_MSEC10*60
#define TICK_MSEC800 TICK_MSEC10*80
#define TICK_MSEC1200 (TICK_MSEC10*120-50)
#define TICK_MSEC1500 (TICK_MSEC10*150-50)
#define TICK_STILL_PRESSED_STEP TICK_MSEC20
#define TICK_TH_PRESS_WAIT TICK_MSEC50
#define TICK_TH_SHORT_PRESS TICK_MSEC100
#define TICK_TH_LONG_PRESS TICK_MSEC1200//TICK_MSEC500
#define TICK_TH_STILL_PRESS TICK_MSEC1500//TICK_MSEC800
#define LONG_PRESS_NONE 0xffff
#define LONG_PRESS_ONCE TICK_TH_STILL_PRESS
#define LONG_PRESS_HOLD_LONG 0
#define LONG_PRESS_HOLD_SHORT (TICK_TH_LONG_PRESS-TICK_TH_PRESS_WAIT)
#define KEY_RELEASE 0x00
#define KEY_HOLD 0x01
#define KEY_PROCESS_ONCE 0x00
#define KEY_PROCESS_CONTINUE 0x02
#define Set_Key_Release() g_KeyInfo.HoldOn = KEY_RELEASE
#define Set_Key_Process_Once() g_KeyInfo.HoldOn = (KEY_HOLD|KEY_PROCESS_ONCE)
#define Set_Key_Process_Continue() g_KeyInfo.HoldOn = (KEY_HOLD|KEY_PROCESS_CONTINUE)
#define If_Key_Process_Once() (g_KeyInfo.HoldOn == (KEY_HOLD|KEY_PROCESS_ONCE))
#define If_Key_Process_Continue() (g_KeyInfo.HoldOn == (KEY_HOLD|KEY_PROCESS_CONTINUE))
#define If_Key_Press_Release() (g_KeyInfo.HoldOn == KEY_RELEASE)
#define If_Key_Press_Hold() ((g_KeyInfo.HoldOn&KEY_HOLD) == KEY_HOLD)
#define F_KEY_SCAN_KICK F_Sys_2msec_kick
typedef struct _KEY_INFO
{
UINT8 Val;
UINT8 HoldOn;
UINT8 Status;
UINT16 Duration;
UINT16 Interval;
UINT16 KeyHoldPeriod;
} KEY_INFO;
typedef struct
{
UINT8 KeyParam;
UINT8 KeyCode;
}KEY_PARAM_CONV;
typedef struct
{
UINT8 KeyMax;
KEY_PARAM_CONV Cfg[16];
}KEY_GET_PARAM;
typedef struct
{
UINT8 KeyCodeIdx;
UINT16 LongKeyPeriod;
}KEY_PARAM;
extern KEY_INFO g_KeyInfo;
extern UINT16 g_uiKeyCode;
extern void Key_Scan(UINT8 m_ucKeyCode);
#endif
文件上传了
Keyourdev_584418KBEHSB.rar(文件大小:3K) (原文件名:Key.rar) |
|