在常见的电子产品中,经常会用到按键来实现一些功能,如切换界面,长按按键操作一些特殊功能。本文讲述基于MDK RTX系统的一种独立按键键值检测,能够实现按键检测,同时多个按键按下检测,长按按键检测功能,并具有软件防抖功能。
#define KEY_START_HOLD_TIME 200 //长按时间,2秒
//键值
enum{
K_IDLE,
K_PRESSDOWN_KEY12,
K_PRESSDOWN_KEY14,
K_PRESSDOWN_KEY1 = 0x11, //按下
K_REPEAT_KEY1, //按下保持
K_PRESSUP_KEY1, //按下抬起
K_PRESSHOLD_DOWN_KEY1, //长按下,未抬起
K_PRESSHOLD_UP_KEY1, //长按下,抬起
K_PRESSDOWN_KEY2 = 0x21,
K_REPEAT_KEY2,
K_PRESSUP_KEY2,
K_PRESSHOLD_DOWN_KEY2,
K_PRESSHOLD_UP_KEY2,
K_PRESSDOWN_KEY3 = 0x31,
K_REPEAT_KEY3,
K_PRESSUP_KEY3,
K_PRESSHOLD_DOWN_KEY3,
K_PRESSHOLD_UP_KEY3,
K_PRESSDOWN_KEY4 = 0x41,
K_REPEAT_KEY4,
K_PRESSUP_KEY4,
K_PRESSHOLD_DOWN_KEY4,
K_PRESSHOLD_UP_KEY4,
};
__task void Task_KeyScan(void)
{
static U16 keystatus = 0xffff; //用4位表示一个按键的动作过程,U16表示四个按键的动作工程
static U8 keyHoldFlag = 0x00;
static U16 key1_holdTimer = 0;
static U16 key2_holdTimer = 0;
static U16 key3_holdTimer = 0;
static U16 key4_holdTimer = 0;
while(1)
{
os_dly_wait(OS_10MS); //该任务每10ms执行一次,如果没有操作系统,可以通过定时器中断函数调用
keystatus <<= 1;
keystatus |= 0x1111;
if(!KEY1)
keystatus &= 0xFFFE; //按键1
if(!KEY2)
keystatus &= 0xFFEF; //按键2
if(!KEY3)
keystatus &= 0xFEFF; //按键3
if(!KEY4)
keystatus &= 0xEFFF; //按键4
if((keystatus&0xF00F) == 0xC000 || (keystatus&0xF00F) == 0x000C)
{
GU8_KeyData = K_PRESSDOWN_KEY14; // key1 key4 同时按下
}
if((keystatus&0x000F)==0x000C)
{
// key1 按下
GU8_KeyData = K_PRESSDOWN_KEY1;
key1_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~1;
}
else if((keystatus&0x00F0)==0x00C0)
{
// key2 按下
GU8_KeyData = K_PRESSDOWN_KEY2;
key2_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~2;
}
else if((keystatus&0x0F00)==0x0C00)
{
// key3 按下
GU8_KeyData = K_PRESSDOWN_KEY3;
key3_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~4;
}
else if((keystatus&0xF000)==0xC000)
{
// key4 按下
GU8_KeyData = K_PRESSDOWN_KEY4;
key4_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~8;
}
else if((keystatus&0x000F)==0x0000 && !key1_holdTimer)
{
//key1 hold
if(keyHoldFlag&1)
{
GU8_KeyData = K_REPEAT_KEY1;
}
else
{
keyHoldFlag |= 1;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY1;
}
}
else if((keystatus&0x00F0)==0x0000 && !key2_holdTimer)
{
// key2 hold
if(keyHoldFlag&2)
{
GU8_KeyData = K_REPEAT_KEY2;
}
else
{
keyHoldFlag |= 2;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY2;
}
}
else if((keystatus&0x0F00)==0x0000 && !key3_holdTimer)
{ // key3 hold
if(keyHoldFlag&4)
{
GU8_KeyData = K_REPEAT_KEY3;
}
else
{
keyHoldFlag |= 4;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY3;
}
}
else if((keystatus&0xF000)==0x0000 && !key4_holdTimer)
{ // key4 hold
if(keyHoldFlag&8){
GU8_KeyData = K_REPEAT_KEY4;
}
else{
keyHoldFlag |= 8;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY4;
}
}
else if((keystatus&0x000F)==0x0003)
{ // key1 弹起
if(keyHoldFlag&1) //有key1Hold标志,表示长按
{
GU8_KeyData = K_PRESSHOLD_UP_KEY1;
}
else
{
GU8_KeyData = K_PRESSUP_KEY1;
}
}
else if((keystatus&0x00F0)==0x0030)
{ // key2 弹起
if(keyHoldFlag&2)
{
GU8_KeyData = K_PRESSHOLD_UP_KEY2;
}
else
{
GU8_KeyData = K_PRESSUP_KEY2;
}
}
else if((keystatus&0x0F00)==0x0300)
{ // key3 弹起
if(keyHoldFlag&4)
{
GU8_KeyData = K_PRESSHOLD_UP_KEY3;
}
else
{
GU8_KeyData = K_PRESSUP_KEY3;
}
}
else if((keystatus&0xF000)==0x3000)
{ // key4 弹起
if(keyHoldFlag&8)
{
GU8_KeyData = K_PRESSHOLD_UP_KEY4;
}
else
{
GU8_KeyData = K_PRESSUP_KEY4;
}
}
if(key1_holdTimer)key1_holdTimer--;
if(key2_holdTimer)key2_holdTimer--;
if(key3_holdTimer)key3_holdTimer--;
if(key4_holdTimer)key4_holdTimer--;
}
}
#define KEY_START_HOLD_TIME 200 //长按时间,2秒
//键值
enum{
K_IDLE,
K_PRESSDOWN_KEY12,
K_PRESSDOWN_KEY14,
K_PRESSDOWN_KEY1 = 0x11, //按下
K_REPEAT_KEY1, //按下保持
K_PRESSUP_KEY1, //按下抬起
K_PRESSHOLD_DOWN_KEY1, //长按下,未抬起
K_PRESSHOLD_UP_KEY1, //长按下,抬起
K_PRESSDOWN_KEY2 = 0x21,
K_REPEAT_KEY2,
K_PRESSUP_KEY2,
K_PRESSHOLD_DOWN_KEY2,
K_PRESSHOLD_UP_KEY2,
K_PRESSDOWN_KEY3 = 0x31,
K_REPEAT_KEY3,
K_PRESSUP_KEY3,
K_PRESSHOLD_DOWN_KEY3,
K_PRESSHOLD_UP_KEY3,
K_PRESSDOWN_KEY4 = 0x41,
K_REPEAT_KEY4,
K_PRESSUP_KEY4,
K_PRESSHOLD_DOWN_KEY4,
K_PRESSHOLD_UP_KEY4,
};
__task void Task_KeyScan(void)
{
static U16 keystatus = 0xffff; //用4位表示一个按键的动作过程,U16表示四个按键的动作工程
static U8 keyHoldFlag = 0x00;
static U16 key1_holdTimer = 0;
static U16 key2_holdTimer = 0;
static U16 key3_holdTimer = 0;
static U16 key4_holdTimer = 0;
while(1)
{
os_dly_wait(OS_10MS); //该任务每10ms执行一次,如果没有操作系统,可以通过定时器中断函数调用
keystatus <<= 1;
keystatus |= 0x1111;
if(!KEY1)
keystatus &= 0xFFFE; //按键1
if(!KEY2)
keystatus &= 0xFFEF; //按键2
if(!KEY3)
keystatus &= 0xFEFF; //按键3
if(!KEY4)
keystatus &= 0xEFFF; //按键4
if((keystatus&0xF00F) == 0xC000 || (keystatus&0xF00F) == 0x000C)
{
GU8_KeyData = K_PRESSDOWN_KEY14; // key1 key4 同时按下
}
if((keystatus&0x000F)==0x000C)
{
// key1 按下
GU8_KeyData = K_PRESSDOWN_KEY1;
key1_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~1;
}
else if((keystatus&0x00F0)==0x00C0)
{
// key2 按下
GU8_KeyData = K_PRESSDOWN_KEY2;
key2_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~2;
}
else if((keystatus&0x0F00)==0x0C00)
{
// key3 按下
GU8_KeyData = K_PRESSDOWN_KEY3;
key3_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~4;
}
else if((keystatus&0xF000)==0xC000)
{
// key4 按下
GU8_KeyData = K_PRESSDOWN_KEY4;
key4_holdTimer = KEY_START_HOLD_TIME;
keyHoldFlag &= ~8;
}
else if((keystatus&0x000F)==0x0000 && !key1_holdTimer)
{
//key1 hold
if(keyHoldFlag&1)
{
GU8_KeyData = K_REPEAT_KEY1;
}
else
{
keyHoldFlag |= 1;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY1;
}
}
else if((keystatus&0x00F0)==0x0000 && !key2_holdTimer)
{
// key2 hold
if(keyHoldFlag&2)
{
GU8_KeyData = K_REPEAT_KEY2;
}
else
{
keyHoldFlag |= 2;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY2;
}
}
else if((keystatus&0x0F00)==0x0000 && !key3_holdTimer)
{ // key3 hold
if(keyHoldFlag&4)
{
GU8_KeyData = K_REPEAT_KEY3;
}
else
{
keyHoldFlag |= 4;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY3;
}
}
else if((keystatus&0xF000)==0x0000 && !key4_holdTimer)
{ // key4 hold
if(keyHoldFlag&8){
GU8_KeyData = K_REPEAT_KEY4;
}
else{
keyHoldFlag |= 8;
GU8_KeyData = K_PRESSHOLD_DOWN_KEY4;
}
}
else if((keystatus&0x000F)==0x0003)
{ // key1 弹起
if(keyHoldFlag&1) //有key1Hold标志,表示长按
{
GU8_KeyData = K_PRESSHOLD_UP_KEY1;
}
else
{
GU8_KeyData = K_PRESSUP_KEY1;
}
}
else if((keystatus&0x00F0)==0x0030)
{ // key2 弹起
if(keyHoldFlag&2)
{
GU8_KeyData = K_PRESSHOLD_UP_KEY2;
}
else
{
GU8_KeyData = K_PRESSUP_KEY2;
}
}
else if((keystatus&0x0F00)==0x0300)
{ // key3 弹起
if(keyHoldFlag&4)
{
GU8_KeyData = K_PRESSHOLD_UP_KEY3;
}
else
{
GU8_KeyData = K_PRESSUP_KEY3;
}
}
else if((keystatus&0xF000)==0x3000)
{ // key4 弹起
if(keyHoldFlag&8)
{
GU8_KeyData = K_PRESSHOLD_UP_KEY4;
}
else
{
GU8_KeyData = K_PRESSUP_KEY4;
}
}
if(key1_holdTimer)key1_holdTimer--;
if(key2_holdTimer)key2_holdTimer--;
if(key3_holdTimer)key3_holdTimer--;
if(key4_holdTimer)key4_holdTimer--;
}
}