小白嵌入式学习记录----按键状态机

嵌入式编程:实现按键状态机

1.状态机的好处

        状态机是一种用于管理程序或系统行为的模型,它将复杂的状态转换逻辑简化为可预测的模式。以下是状态机的核心优势:避免阻塞主程序,将一个长时间的动作分为多个短时间的动作。程序在执行时,执行其他程序+执行动作1+执行其他程序+执行动作2+执行其他程序+执行动作3。类似时间切片的轮询方法。

2.检测按键长按与短按

  • 状态0:等待按键按下

  • 状态1:消抖并检测短按

  • 状态2:检测长按

  • 状态3:长按保持状态

状态机关系图:

/*-----在.h文件中定义-----*/
typedef enum{
KEY_RELEASE = 0,    //松手
KEY_SHORT,          //短按
KEY_LONG,           //长按
}KEY_EVENT;

/* 可调参数 ---------------------------------------------------- */
#define KEY_GPIO_PORT   GPIOE
#define KEY_GPIO_PIN    GPIO_Pin_2
#define KEY_DOWN_LEVEL  0          // 0 = 低电平按下
#define SHORT_TICKS     20         // 20*10 ms = 200 ms 作为短按
#define LONG_TICKS      100        // 100*10 ms = 1 s 作为长按
/*-------------------------------------------------------------*/


/*-----在.c文件中-----*/
KEY_EVENT key_fsm()
{
	static uint8_t state   = 0;    // 状态
    static uint16_t cnt    = 0;    // 计时器
    KEY_EVENT ret = KEY_RELEASE;
	
	switch(state)
	{
		case 0:
			if(GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN) == KEY_DOWN_LEVEL)	//检测按键按下
			{
				state = 1;
				cnt = 0;
			}
			break;	
		case 1:	
			if(GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN) == KEY_DOWN_LEVEL)	//确认按键按下+消抖
			{
				cnt++;
				if(cnt >= SHORT_TICKS)	//消抖(时间小于短按)并确认为短按
				{
					state = 2;
					ret   = KEY_SHORT;  // 产生短按事件
				}
			}
			else
			{
				state = 0;		//抖动/误触
			}
			break;
		case 2:
			if(GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN) == KEY_DOWN_LEVEL)	//确认按键按下
			{
				cnt++;
				if(cnt >= LONG_TICKS)		//确认长按
				{
					state = 3;
					ret   = KEY_LONG;   // 产生长按事件
				}
			}
			else
			{
				state = 0;		//短按后松开
			}
			break;
		case 3:
			if(GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN) != KEY_DOWN_LEVEL)
			{
				state = 0;
			}
			break;
	}
	return ret;
}

代码实现:

3.检测按键双击

  • 状态0:等待按键按下

  • 状态1:检测第一次按下抬起

  • 状态2:检测第二按下

  • 状态3:长按保持状态

状态机关系图:

void Check_Key_click()
{
	static uint8_t state = 0;
	static uint16_t cnt_Down = 0;	//用于按下计数
	static uint16_t cnt_Up = 0;		//用于松开计数
	
	switch(state)
	{
	case 0:
		if(!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4))	//检测按键按下
		{
			state = 1;
			cnt_Down = 0;
			cnt_Up = 0;
		}
		break;
	case 1:
		if(!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4))	//检测按键按下
		{
			cnt_Down++;
			if(cnt_Down >= 5);		//按下消抖50ms
			if(cnt_Down >= 200)		//按下不松手,超时2s
			{
				state = 0;
			}
		}
		else if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4))	//检测按键松手
		{
			cnt_Up++;
			if(cnt_Up >=5)	//松手消抖50ms
			{
				state = 2;		//松手后进入状态2
				cnt_Down = 0;	//计数清0
				cnt_Up = 0;		
			}
		}
		break;
	case 2:			//状态2,再次检测按下
		if(!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4))	//检测按键按下
		{
			cnt_Down ++;
			if(cnt_Down >= 5)		//按下消抖50ms
			{
				state = 3;
				cnt_Down = 0;
			}
		}
		cnt_Up++;				//高电平计数器自增
		if(cnt_Up >= 200)		//检测第一次松手后,不及时按超时2s
		{
			state = 0;
		}
		break;
	case 3:
		if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4))	//检测按键按下
		{
            state = 0;
		}
		break;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值