五方向按键ADC识别(状态机实现)

借鉴别人的文章借鉴写的。

ADC初始化就不多说了。

首先头文件:.h

/*键盘扫描间隔,按键响应时间 20 40 80 ms*/
/*不精准延时40ms,调试的键值*/
#define KEY_NONE    		0x2E
#define KEY_MENU 			0x27
//#define KEY_MENU_LONG 	0x67
#define KEY_UP				0x1F
#define KEY_UP_LONG 		0X5F
#define KEY_DOWN			0x17
#define KEY_DOWN_LONG 		0X57
#define KEY_ENTER			0x0F
//#define KEY_ENTER_LONG		0x4F

#define S_KEY    	1                  // 短按
#define L_KEY     	2                // 长按


#define LONG_KEY_TIME       100     // LONG_KEY_TIME*10MS = 4S
#define SINGLE_KEY_TIME     4       // SINGLE_KEY_TIME*10MS = 40MS

typedef enum {
    KEY_CHECK=0x00,  // 按键检测
    KEY_CONFIRM=0x01,   // 按键确认
    KEY_TYPE=0x02, // 按键类型判断
	KEY_RELEASE=0x03,	//按键释放
} Key_State;

.c.文件

精准延时可以使用定时器


/*识别各个按键类型,需循环实现状态机,会break*/
uint8_t Key_driver(void)
{
	static Key_State key_state=KEY_CHECK;
	static uint8_t key_time=0;
	uint8_t key_value,key_return;
	
	key_return=KEY_NONE;
	
	key_value=TM1650_Read_key();
	
	switch(key_state)
	{
		case KEY_CHECK://识别有无按键按下,等待按键
		{
			if(key_value==KEY_NONE)//无按键按下
			{
				key_time=0;//清零计数
				key_state=KEY_CONFIRM;
			}
		}
		break;
		case KEY_CONFIRM://按键确认,度过2 个键扫周期
		{
			if(key_value!=KEY_NONE)
			key_time++;//一次10ms
			if(key_time>=SINGLE_KEY_TIME)//大于2 个键扫周期,说明按键按下
			{
				key_state=KEY_TYPE;
			}
			
		}
		break;
		case KEY_TYPE://长短按判断
		{
			if(key_value!=KEY_NONE)//在长按时间内释放,说明短按
			{
				key_state=KEY_CHECK;//清零时间计数
				switch(key_value)//短按类型
				{
					case KEY_MENU:
					{
						key_return=KEY_MENU|S_KEY;
						return key_return;
					}
					case KEY_UP:
					{
						key_return=KEY_UP|S_KEY;
						return key_return;
					}
					case KEY_DOWN:
					{
						key_return=KEY_DOWN|S_KEY;
						return key_return;
					}
					case KEY_ENTER:
					{
						key_return=KEY_ENTER|S_KEY;
						return key_return;
					}
				}
			}
			else
			{
				key_time++;
				if(key_time>=LONG_KEY_TIME)//大于等于长按周期,说明按键长按
				{
					key_state=KEY_RELEASE;//去等待按键释放	
					switch(key_value)//长按类型
					{
//						case KEY_MENU:
//						{
//							key_return=KEY_MENU|L_KEY;
//							return key_return;
//						}
						case KEY_UP:
						{
							key_return=KEY_UP|L_KEY;
							return key_return;
						}
						case KEY_DOWN:
						{
							key_return=KEY_DOWN|L_KEY;
							return key_return;
						}
//						case KEY_ENTER:
//						{
//							key_return=KEY_ENTER|L_KEY;
//							return key_return;
//						}
					}
				 }
			  }
		  }
		break;
		case KEY_RELEASE://等待按键释放
		{
			if(key_value==KEY_NONE)//按键释放
			{
				key_state=KEY_CHECK;
				key_return=KEY_NONE;
				return key_return;	
			}
		}
		break;
		default://避免上电或通信波动,造成初始键值不一致的状况
			key_state=KEY_CHECK;
			break;
	}
	/*按键识别完,*/
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值