单片机通用按键驱动模块

支持单击长按长按(超过指定时间)按住,四种状态。前三个状态都是按键松开生效,代码简单,可以自行添加修改。

本模块不如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)
	    {
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RayC02

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

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

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

打赏作者

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

抵扣说明:

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

余额充值