基于单片机的多按键多状态检测方法



在常见的电子产品中,经常会用到按键来实现一些功能,如切换界面,长按按键操作一些特殊功能。本文讲述基于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--;
	}
}

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值