多功能按键

多功能按键

本示例主要实现多功能按键:短按(按下与释放),长按(长按按下、连续、释放),短按多次连击功能;

H文件



#ifndef _KEY_H_
#define _KEY_H_

#include "stdio.h"
#include "stdint.h"

#define MULTI_CLICK		1
#define LONG_CONTINUE	1


typedef enum
{
	eKeyLow,
	eKeyHigh,
}eKey;

typedef enum
{
	eKeyNull,
	eKeyPress,
	eKeyRelease,
	eKeyLongPress,
	#if LONG_CONTINUE
	eKeyLongContinnue,
	#endif
	eKeyLongRelease,
}eKeyStatus;

typedef int (*pKeyCallBackFunction)(void* parm);

typedef struct _Key_CB_t
{
	pKeyCallBackFunction pKeyPressCB;
	pKeyCallBackFunction pKeyReleaseCB;
	pKeyCallBackFunction pKeyLongPressCB;
	#if LONG_CONTINUE
	pKeyCallBackFunction pKeyLongContinueCB;
	#endif
	pKeyCallBackFunction pKeyLongReleaseCB;
}KeyCB_t;

typedef struct _Key_t
{
	eKeyStatus ekey;
	uint16_t usId;
	uint16_t usDebounce;
	uint16_t usShortPressDebounce;
	uint16_t usLongPressDebounce;
	#if MULTI_CLICK
	uint8_t ucShortKeyTimes;
	uint16_t usReleaseDebounce;
	uint16_t usShortKeyReleaseDeobunce;
	#endif
	#if LONG_CONTINUE
	uint16_t usLongContinueDebounce;
	#endif
	KeyCB_t* pKeyCB;
}KeyInfo_t;

#define KEY_CNT		1
#define KEY_BUF_CNT	((KEY_CNT>>4) + ((KEY_CNT&0x0F)?1:0))		//16bit Algin

void KeyInit(void);
void KeyScan(void);
void KeyProcess(void);

#endif

C文件


#include "Key.h"
#include "main.h"
uint16_t KeyScanBuf[KEY_BUF_CNT];
KeyInfo_t KeyInfo[KEY_CNT];

int KeyShortPress(void * parm)
{
	printf("%s\r\n",__FUNCTION__);
	return 0;
}

int KeyShortRelease(void * parm)
{
	#if MULTI_CLICK
	printf("%s,t=%d\r\n",__FUNCTION__,((KeyInfo_t*)parm)->ucShortKeyTimes);
	#else
	printf("%s\r\n",__FUNCTION__);
	#endif
	return 0;
}

int KeyLongPress(void * parm)
{
	printf("%s\r\n",__FUNCTION__);
	return 0;
}
int KeyLongContinue(void * parm)
{
	printf("%s\r\n",__FUNCTION__);
	return 0;
}
int KeyLongRelease(void * parm)
{
	printf("%s\r\n",__FUNCTION__);
	return 0;
}

KeyCB_t KeyCbBuf=
{
	KeyShortPress,
	KeyShortRelease,
	KeyLongPress,
	#if LONG_CONTINUE
	KeyLongContinue,
	#endif
	KeyLongRelease,
};

void KeyInit(void)
{
	for(int i=0;i<KEY_CNT;i++)
	{
		KeyInfo[i].ekey = eKeyNull;
		KeyInfo[i].usId = i;
		KeyInfo[i].usDebounce = 0;
		KeyInfo[i].usShortPressDebounce = 4;
		KeyInfo[i].usLongPressDebounce = 24;//240ms
		#if MULTI_CLICK
		KeyInfo[i].ucShortKeyTimes = 0;
		KeyInfo[i].usReleaseDebounce = 0;
		KeyInfo[i].usShortKeyReleaseDeobunce = 40;//400ms
		#endif
		#if LONG_CONTINUE
		KeyInfo[i].usLongContinueDebounce = 0;
		#endif
		KeyInfo[i].pKeyCB = &KeyCbBuf;
	}
}

void KeyScan(void)
{
	KeyScanBuf[0] = HAL_GPIO_ReadPin(KEY_UP_GPIO_Port,KEY_UP_Pin);
}

void KeyDetect(uint8_t * pKey,KeyInfo_t* pKeyInfo,uint16_t KeyCnt)
{
	for(int i=0;i<KeyCnt;i++)
	{
		if ((pKey[i>>3]&(0x01<<(i&0x07))) == eKeyLow)
		{
			pKeyInfo->usDebounce++;
			if (pKeyInfo->ekey == eKeyLongPress)
			{
				#if LONG_CONTINUE
				pKeyInfo->ekey = eKeyLongContinnue;
				pKeyInfo->usLongContinueDebounce = pKeyInfo->usDebounce + pKeyInfo->usLongPressDebounce;
				#endif
			}
			#if LONG_CONTINUE
			else if ((pKeyInfo->ekey == eKeyLongContinnue) && (pKeyInfo->usLongContinueDebounce == pKeyInfo->usDebounce))
			{
				if (pKeyInfo->pKeyCB->pKeyLongContinueCB != NULL)
				{
					pKeyInfo->pKeyCB->pKeyLongContinueCB(pKeyInfo);
				}
				pKeyInfo->usLongContinueDebounce = pKeyInfo->usDebounce + pKeyInfo->usLongPressDebounce;
			}
			#endif
			else if ((pKeyInfo->ekey != eKeyLongPress)&&(pKeyInfo->usDebounce == pKeyInfo->usLongPressDebounce))
			{
				pKeyInfo->ekey = eKeyLongPress;
				if (pKeyInfo->pKeyCB->pKeyLongPressCB != NULL)
				{
					pKeyInfo->pKeyCB->pKeyLongPressCB(pKeyInfo);
				}
			}
			else if (pKeyInfo->usDebounce == pKeyInfo->usShortPressDebounce)
			{
				pKeyInfo->ekey = eKeyPress;
				if (pKeyInfo->pKeyCB->pKeyPressCB != NULL)
				{
					pKeyInfo->pKeyCB->pKeyPressCB(pKeyInfo);
				}
				#if MULTI_CLICK
				pKeyInfo->ucShortKeyTimes++;
				pKeyInfo->usReleaseDebounce = 0;
				#endif
			}
		}
		else
		{
			if (pKeyInfo->ekey == eKeyPress)
			{
				#if MULTI_CLICK
				pKeyInfo->usReleaseDebounce++;
				if (pKeyInfo->usReleaseDebounce > pKeyInfo->usShortKeyReleaseDeobunce)
				{
					//short key release
					if (pKeyInfo->pKeyCB->pKeyReleaseCB != NULL)
					{
						pKeyInfo->pKeyCB->pKeyReleaseCB(pKeyInfo);
						pKeyInfo->ucShortKeyTimes = 0;
						pKeyInfo->usReleaseDebounce = 0;
						pKeyInfo->ekey = eKeyNull;
					}
				}
				#else
				if (pKeyInfo->pKeyCB->pKeyReleaseCB != NULL)
				{
					pKeyInfo->pKeyCB->pKeyReleaseCB(pKeyInfo);
					pKeyInfo->ekey = eKeyNull;
				}
				#endif
			}
			#if LONG_CONTINUE
			else if ((pKeyInfo->ekey == eKeyLongContinnue)||(pKeyInfo->ekey == eKeyLongPress))
			{
				if (pKeyInfo->pKeyCB->pKeyLongReleaseCB != NULL)
				{
					pKeyInfo->pKeyCB->pKeyLongReleaseCB(pKeyInfo);
					#if MULTI_CLICK
					pKeyInfo->ucShortKeyTimes = 0;
					pKeyInfo->usReleaseDebounce = 0;
					#endif
					pKeyInfo->ekey = eKeyNull;
				}
			}
			#else
			else if (pKeyInfo->ekey == eKeyLongPress)
			{
				if (pKeyInfo->pKeyCB->pKeyLongReleaseCB != NULL)
				{
					pKeyInfo->pKeyCB->pKeyLongReleaseCB(pKeyInfo);
					#if MULTI_CLICK
					pKeyInfo->ucShortKeyTimes = 0;
					pKeyInfo->usReleaseDebounce = 0;
					#endif
					pKeyInfo->ekey = eKeyNull;
				}
			}
			#endif
			pKeyInfo->usDebounce = 0;
		}
		pKeyInfo++;
	}
}

void KeyProcess(void)
{
	KeyScan();
	KeyDetect((uint8_t*)KeyScanBuf,KeyInfo,KEY_CNT);
}

使用说明

#define MULTI_CLICK 1 //设置是否使能连击功能
#define LONG_CONTINUE 1//设置是否使能长按连续功能

typedef int (pKeyCallBackFunction)(void parm);

typedef struct _Key_CB_t
{
pKeyCallBackFunction pKeyPressCB;
pKeyCallBackFunction pKeyReleaseCB;
pKeyCallBackFunction pKeyLongPressCB;
#if LONG_CONTINUE
pKeyCallBackFunction pKeyLongContinueCB;
#endif
pKeyCallBackFunction pKeyLongReleaseCB;
}KeyCB_t;
以上为按键回调函数结构体。

typedef struct _Key_t
{
eKeyStatus ekey;
uint16_t usId;
uint16_t usDebounce;
uint16_t usShortPressDebounce;
uint16_t usLongPressDebounce;
#if MULTI_CLICK
uint8_t ucShortKeyTimes;
uint16_t usReleaseDebounce;
uint16_t usShortKeyReleaseDeobunce;
#endif
#if LONG_CONTINUE
uint16_t usLongContinueDebounce;
#endif
KeyCB_t* pKeyCB;
}KeyInfo_t;
以上为单个按键结构体。

#define KEY_CNT 1//定义按键个数

按键初始化

在KeyInit里面初始化按键,设置每个按键的相关信息,特别是其回调函数。

按键扫描

请在KeyScan里面实现每个按键的扫描,每个按键状态占用1个bit,保存在KeyScanBuf里面。

按键处理

请周期性调用KeyProcess,其实现按键扫描和处理整个过程。
如果有连击功能,连接次数结果请在KeyShortRelease里面调用((KeyInfo_t*)parm)->ucShortKeyTimes获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值