STM32按键状态机的实现

目录

一、按键状态机的作用

二、按键状态机的实现

1、按键状态机的宏定义

2、按键状态机的枚举与相关结构体

3、按键状态机的函数实现


一、按键状态机的作用

一般的按键状态机一般都具有以下功能:

  • 能够判断哪个按键按下
  • 能够判断按键是长按或者短按
  • 能够记录对应按键按下对应的次数

实现思想:

  • 首先,通过定时器或者查询方式等周期性查询按键状态机的状态
  • 接着在按键状态机中,需要获取得到对应按下的按键,然后通过对按键的前后状态进行对比,如果没有改变,则增加按键时间。如果按键松开,则对按键结构体进行修改,将对应信息赋值给按键结构体。

使用方法:

  • 通过不断检测按键状态机,当按键状态机改变后。通过对按键结构体的检索,可以得知按下按键的按键编号、按键时间长短、按键按下次数。
  • 然后执行对应按键的功能

二、按键状态机的实现

1、按键状态机的宏定义

/* 按键key的编号 */
#define KEY_DEFAULT_NUM					0x00
#define KEY_0_NUM						0x01
#define KEY_1_NUM						0x02
#define KEY_2_NUM						0x04
#define KEY_UP_NUM						0x08
#define KEY_ALL_NUM						0xFF

/* 按键时长状态定义 */
#define KEY_PRESS_SHORT				10U

2、按键状态机的枚举与相关结构体

/* 按键状态对比 */
typedef enum
{
	No_Change = 0,
	Pressed_State,
	Release_State,

}exKeyCompareStateEnum;

/* 按键按下时间长短 */
typedef enum
{
	Key_State_Default = 0,
	Key_State_Short,
	Key_State_Long,

}exKeyStateEnum;

/* 按键结构体 */
typedef struct
{
	uint8_t ucKeyNum;	/* 按键编号 */
	uint8_t ucKeyState;	/* 按键时长状态 */
	uint8_t ucKeyCount; /* 按键次数 */

}exKeyTypeDef;

3、按键状态机的函数实现

/**
 * 按键状态机
 * @para 	ucKeyNum: 需要检测的按键编号
 * @retval	0: 状态未改变 	1: 状态改变
 */
uint8_t ucKeyMachine(uint8_t ucKeyNum)
{
	static uint8_t ucNewKeyNum = 0, ucOldKeyNum = 0;
	static uint8_t ucKeyPressedTime = 0;
	static uint8_t ucEndFlag = 0;
	uint8_t ucKeyState = No_Change;

	/* 对应按键编号的按键状态 */
	ucNewKeyNum = ucKeyScan(ucKeyNum);

	/* 新按键状态 判断与处理 */
	ucKeyState = ucKeyStateCompare(ucNewKeyNum, ucOldKeyNum);
	switch(ucKeyState)
	{
	case No_Change: 	ucKeyPressedTime++;  break;								/* 按键状态改变,则增加按键时间 */
	case Pressed_State: ucOldKeyNum = ucNewKeyNum; ucKeyPressedTime = 0; break;	/* 按键按下,则更改按键缓存,并且将按键时间置0 */
	case Release_State: ucEndFlag = 1; break;									/* 按键松开,则进入按键结束 */
	}

	/* 按键结束 */
	if(ucEndFlag == 1)
	{
		/* 更新按键次数 */
		if(ex_KeyHandle.ucKeyNum == ucOldKeyNum)
			ex_KeyHandle.ucKeyCount++;
		else
		{
			ex_KeyHandle.ucKeyNum = ucOldKeyNum;
			ex_KeyHandle.ucKeyCount = 0;
		}

		/* 更新按键状态时长 */
		if(ucKeyPressedTime >= KEY_PRESS_SHORT)
			ex_KeyHandle.ucKeyState = Key_State_Long;
		else
			ex_KeyHandle.ucKeyState = Key_State_Short;

		/* 参数初始化 */
		ucEndFlag = 0;
		ucOldKeyNum = 0;
		ucKeyPressedTime = 0;

		return 1;
	}

	return 0;
}


/**
 * 按键扫描
 * @para 	ucKeyNum: 按键编号
 * @retval 	ucPressedKeyNum: 返回对应按下按键的编号, 未按下则返回 0
 */
uint8_t ucKeyScan(uint8_t ucKeyNum)
{
	uint8_t ucPressedKeyNum = 0;

	if(ucKeyNum & KEY_0_NUM)
	{
		if(HAL_GPIO_ReadPin(KEY_PORT, KEY_0_PIN) == GPIO_PIN_RESET)
			ucPressedKeyNum |= KEY_0_NUM;
	}

	if(ucKeyNum & KEY_1_NUM)
	{
		if(HAL_GPIO_ReadPin(KEY_PORT, KEY_1_PIN) == GPIO_PIN_RESET)
			ucPressedKeyNum |= KEY_1_NUM;
	}

	if(ucKeyNum & KEY_2_NUM)
	{
		if(HAL_GPIO_ReadPin(KEY_PORT, KEY_2_PIN) == GPIO_PIN_RESET)
			ucPressedKeyNum |= KEY_2_NUM;
	}

	if(ucKeyNum & KEY_UP_NUM)
	{
		if(HAL_GPIO_ReadPin(KEY_UP_PORT, KEY_UP_PIN) == GPIO_PIN_SET)
			ucPressedKeyNum |= KEY_UP_NUM;
	}

	return ucPressedKeyNum;
}


/**
 * 按键状态前后对比函数
 * @para 	ucNewKeyNum: 新键值状态
 * @para 	ucOldKeyNum: 旧键值状态
 * @retval 	返回对应键值改变的状态
 */
uint8_t ucKeyStateCompare(uint8_t ucNewKeyNum, uint8_t ucOldKeyNum)
{
	if(ucNewKeyNum == ucOldKeyNum)
		return No_Change;
	else if((ucNewKeyNum & ucOldKeyNum) == ucOldKeyNum)
		return Pressed_State;
	else
		return Release_State;
}

 

  • 7
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃鱼的猫丿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值