支持单击、长按、长按(超过指定时间)、按住,四种状态。前三个状态都是按键松开生效,代码简单,可以自行添加修改。
本模块不如MultiButton支持状态多,因为在项目中发现MultiButton这个开源不是十分适配我的程序,并且修改为矩阵键盘不是很好用,所以根据我的个人需求添加了支持组合键的驱动。
程序只给出独立IO按键、如需矩阵键盘只需要更改key_scan函数的接口。变量有点乱,感兴趣可以进一步优化代码
key.h
#ifndef USER_KEY_KEY_H_
#define USER_KEY_KEY_H_
#include "main.h"
void Init_Key(void);
#define LONG_PRESS_THRESHOLD 1000 // 1 second
typedef enum {
KEY_NO = 0,
KEY_SHORT_PRESS,
KEY_LONG_PRESS,
KEY_LONG_PRESS_Long,
KEY_LONG_HOLD,
} KeyPressType;
extern KeyPressType nKeyPressType;
KeyPressType key_process(void);
typedef enum
{
KEY_NONE=((uint16_t)0x0000),
KEY_1=((uint16_t)0x0001),
KEY_2=((uint16_t)0x0002),
KEY_3=((uint16_t)0x0004),
KEY_4=((uint16_t)0x0008),
KEY_5=((uint16_t)0x0010),
KEY_6=((uint16_t)0x0020),
KEY_56 = KEY_5+KEY_6,
KEY_23 = KEY_2+KEY_3,
KEY_36 = KEY_3+KEY_6,
}KEY_VALUE;
extern KEY_VALUE nPreKey;
extern KEY_VALUE nOldPreKey;
extern u8 nDevKeyHold;
#endif /* USER_KEY_KEY_H_ */
key.c
#include "key.h"
uint16_t nkey_status;
uint16_t nkey_OldStatus;
uint32_t nHit_Dly;
uint32_t nKeyDownTime;
uint32_t nKeyHoldTime;
u8 isHoldPress;
KEY_VALUE nPreKey;
KEY_VALUE nOldPreKey;
KeyPressType nKeyPressType;
u8 nDevKeyHold;
void Init_Key(void)
{
nkey_status = 0xffff;
nkey_OldStatus = 0xffff;
nHit_Dly = 0;
nPreKey = KEY_NONE;
nOldPreKey = KEY_NONE;
}
void key_scan(void)
{
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET)
nkey_status &= ~(KEY_2);
else
nkey_status |= KEY_2;
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET)
nkey_status &= ~(KEY_3);
else
nkey_status |= KEY_3;
if(HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) == GPIO_PIN_RESET)
nkey_status &= ~(KEY_4);
else
nkey_status |= KEY_4;
if(HAL_GPIO_ReadPin(KEY5_GPIO_Port, KEY5_Pin) == GPIO_PIN_RESET)
nkey_status &= ~(KEY_5);
else
nkey_status |= KEY_5;
if(HAL_GPIO_ReadPin(KEY6_GPIO_Port, KEY6_Pin) == GPIO_PIN_RESET)
nkey_status &= ~(KEY_6);
else
nkey_status |= KEY_6;
if(HAL_GPIO_ReadPin(POWEROFF_GPIO_Port, POWEROFF_Pin) == GPIO_PIN_RESET)
nkey_status &= ~(KEY_1);
else
nkey_status |= KEY_1;
}
KeyPressType key_process(void)
{
KeyPressType key_press_type = KEY_NO;
key_scan();
if(nkey_OldStatus == nkey_status)
{
if((HAL_GetTick() - nHit_Dly > 50))
{
if(nPreKey > KEY_NONE)
{
if(nkey_status == 0xFFFF)
{
if (HAL_GetTick() - nKeyDownTime >= LONG_PRESS_THRESHOLD*3)
{
key_press_type = KEY_LONG_PRESS_Long;
}
else if (HAL_GetTick() - nKeyDownTime >= LONG_PRESS_THRESHOLD)
{
key_press_type = KEY_LONG_PRESS;
}
else
{
key_press_type = KEY_SHORT_PRESS;
}
isHoldPress = 0;
nDevKeyHold = 0;
nSystemRunTime=0;
nOldPreKey = nPreKey;
nPreKey = KEY_NONE;
}
else if(nkey_status < 0xFFFF && isHoldPress == 0)
{
nOldPreKey = nPreKey;
isHoldPress = 1;
nKeyHoldTime = HAL_GetTick();
}
else if(isHoldPress && ((HAL_GetTick() - nKeyHoldTime) >= LONG_PRESS_THRESHOLD))
{
if(nDevKeyHold==0)
{
nOldPreKey = nPreKey;
key_press_type = KEY_LONG_HOLD;
}
else key_press_type = KEY_NO;
}
return key_press_type;
}
if(nkey_status < 0xFFFF)
{
nKeyDownTime = HAL_GetTick();
}
if((nkey_status & KEY_1) == 0) //hit
{
nPreKey = KEY_1;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & KEY_2) == 0) //hit
{
nPreKey = KEY_2;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & KEY_3) == 0) //hit
{
nPreKey = KEY_3;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & KEY_4) == 0) //hit
{
nPreKey = KEY_4;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & KEY_5) == 0) //hit
{
nPreKey = KEY_5;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & KEY_6) == 0) //hit
{
nPreKey = KEY_6;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & (KEY_5 + KEY_6)) == 0) //hit
{
nPreKey = KEY_5 + KEY_6;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & (KEY_2 + KEY_3)) == 0) //hit
{
nPreKey = KEY_2 + KEY_3;
nHit_Dly = HAL_GetTick();
}
if((nkey_status & (KEY_3 + KEY_6)) == 0) //hit
{
nPreKey = KEY_3 + KEY_6;
nHit_Dly = HAL_GetTick();
}
}
}
else
{
nHit_Dly = HAL_GetTick();
nkey_OldStatus = nkey_status;
}
return key_press_type;
}
主程序
int main()
{
Init_Key();
while(1)
{
nKeyPressType=key_process();
if(nKeyPressType==KEY_SHORT_PRESS)
{
switch(nOldPreKey)
{
case KEY_1:
break;
//........
}
}
if(nKeyPressType==KEY_LONG_HOLD)
{
}
}
}