key组合按键,长短按键,连续按键 识别方案

本文介绍了如何使用宏定义和整型变量实现30键的组合按键控制,包括短按、长按和连续按功能。通过实例代码展示了按键事件处理、按键检测及自定义按键值解析的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.介绍

假如我们有30个按键,要实现识别所有按键的组合短按,组合长按,组合连续按,等等,按规则写出来非常麻烦,我们使用宏定义,整型变量按位检测就很方便。

二.按键基本功能

首先需要基本的按键事件输入。
然后通过对按下按键开始计时,后续按下重置计时。循环检测长按事件。
松开按键触发短按判断。
任意时刻松开触发按键后,后续按下会无效,直到所有按键松开。

三.上程序源码:

key.c:

#include "key.h"
void key_init(void){  									//初始化按键
	GPIO_InitType GPIO_InitStructure;
	SysCtrl_PeripheralClockCmd(CLOCK_PERIPH_GPIO, ENABLE);
	GPIO_InitStructure.GPIO_Pin = KEY_IO_MASK;
	GPIO_InitStructure.GPIO_Mode = GPIO_Input;
	GPIO_InitStructure.GPIO_Pull = DISABLE;			
	GPIO_InitStructure.GPIO_HighPwr = DISABLE;
	GPIO_Init(&GPIO_InitStructure);
}
static void key_send(uint32_t key){
	uint8_t * p = (uint8_t *)&key;
	uint8_t temp[7] = {0};
	temp[0] = 0xAA;
	temp[1] = p[0];
	temp[2] = p[1];
	temp[3] = p[2];
	temp[4] = p[3];
	temp[5] = p[0]+p[1]+p[2]+p[3];
	temp[6] = 0xAA;
	ble_trans_data(7,temp); 
	printf("  [key]:%d \r\n",key);
}
static uint32_t key_all = 0,key_now = 0,clean = 0,count = 0,long_cnt = 0;
static uint32_t key_Always = 0,Alcount = 0;
void key_process(void){
	static uint8_t key[5] = {0};
	key[0] = !GPIO_ReadBit(GPIO_Pin_8);					//电源
	//key[1] = !GPIO_ReadBit(GPIO_Pin_0);					//上
	key[1] = !GPIO_ReadBit(GPIO_Pin_6);					//测试
	key[2] = !GPIO_ReadBit(GPIO_Pin_1);					//下
	key[3] = !GPIO_ReadBit(GPIO_Pin_2);					//左
	key[4] = !GPIO_ReadBit(GPIO_Pin_3);					//右
//=====================================================================按键长短按	
	key_now = ((key[0]<<yr_key_power)|(key[1]<<yr_key_up)|(key[2]<<yr_key_down)|(key[3]<<yr_key_left)|(key[4]<<yr_key_right));
	if(key_now != key_all){	
		if(count++ > delay_t){ 							//消抖
			count = 0;									//消抖
			if(((key_all&key_now)<key_all)&&clean == 0){//短按松开
				key_send(key_all);						//短按发送
				clean = 1;								//松开清除
				long_cnt = 0;	
			}
			key_all = key_now;				
		}			
	}else if(key_all > 0&&clean == 0){					//长按计时
		if(long_cnt++ > delay_long){					//长按触发
			key_send(key_all|(1<<yr_L));				//长按松开发送
			clean = 1;									//长按松开清除
			key_Always = key_all;						//
			long_cnt = 0;
		}
	}
	if(key_now == key_all) 	count = 0;					//消抖
	if(key_all == 0) 		clean = 0;
//===================================================================长按保持	
	if(key_Always == key_all&&key_Always > 0){
		if(Alcount++ > delay_long/10){
			Alcount = 0;
			key_send(key_all|(1<<yr_AL));
		}
	}else {
		Alcount = 0;
		key_Always = 0;
	}
	//printf("   [%d %d %d %d %d] [key_all %d,key_now %d,clean %d,long_cnt %d]\r\n   ",key[0],key[1],key[2],key[3],key[4],key_all,key_now,clean,long_cnt);
}

key.h:

#ifndef __KEY_H_
#define __KEY_H_
#include <stdio.h>
#include "SDK_EVAL_Led.h"
#define WEEKUP_SOURCE				(WAKEUP_IO13)
//#define KEY_IO_MASK 				(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_8)
#define KEY_IO_MASK 				(GPIO_Pin_6|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_8) //ps3测试
#define delay_long					(3*15*400)
#define delay_t						(400)
/************************* KEY VALUE DEFINE *********************/
#define yr_L   		   (0)//长按
#define yr_AL   	   (16)//连续按
#define yr_key_power   (1)//电源
#define yr_key_up	   (2)//上
#define yr_key_down    (3)//下
#define yr_key_left    (4)//左
#define yr_key_right   (5)//右

void key_init(void);
void key_process(void);
#endif

四.如何使用

使用时自定义出需要的按键名称,然后通过按位组合,解析出来。

#define yr_L   		   (0)//长按
#define yr_AL   	   (16)//连续按
#define yr_key_1       (1)//电源
#define yr_key_2	   (2)//上
#define yr_key_3       (3)//下
#define yr_key_4       (4)//左
#define yr_key_5       (5)//右
uint8_t key_get_Value(u_int32_t param){
	switch(param){
		case (1<<yr_key_1):								printf("KEY_MENU_S\n");							return KEY_MENU_S;
		case (1<<yr_key_2):								printf("KEY_POWER_S\n");						return KEY_POWER_S;
		case (1<<yr_key_3):								printf("KEY_CAMERA_S\n");						return KEY_CAMERA_S;
		case (1<<yr_key_4):								printf("KEY_OBSERVATION_S\n");					return KEY_OBSERVATION_S;
		case (1<<yr_key_5):								printf("KEY_RANGING_S\n");						return KEY_RANGING_S;

		case ((1<<yr_key_1)|(1<<yr_L)): 				printf("KEY_MENU_L\n");							return KEY_MENU_L;
		case ((1<<yr_key_2)|(1<<yr_L)): 				printf("KEY_POWER_L\n");						return KEY_POWER_L;
		case ((1<<yr_key_3)|(1<<yr_L)): 				printf("KEY_CAMERA_L\n");						return KEY_CAMERA_L;
		case ((1<<yr_key_4)|(1<<yr_L)): 				printf("KEY_OBSERVATION_L\n");					return KEY_OBSERVATION_L;
		case ((1<<yr_key_5)|(1<<yr_L)): 				printf("KEY_RANGING_L\n");						return KEY_RANGING_L;

		case ((1<<yr_key_1)|(1<<yr_key_4)|(1<<yr_L)): 	printf("KEY_MENU_L_AND_KEY_OBSERVATION_L\n");	return KEY_MENU_L_AND_KEY_OBSERVATION_L;
		case ((1<<yr_key_3)|(1<<yr_key_4)|(1<<yr_L)): 	printf("KEY_CAMERA_L_AND_KEY_OBSERVATION_L\n");	return KEY_CAMERA_L_AND_KEY_OBSERVATION_L;
		case ((1<<yr_key_1)|(1<<yr_key_5)|(1<<yr_L)): 	printf("KEY_MENU_L_AND_KEY_RANGING_L\n");		return KEY_MENU_L_AND_KEY_RANGING_L;

		case ((1<<yr_key_2)|(1<<yr_AL)): 				printf("KEY_POWER_ALWAYS_L\n");						return KEY_POWER_ALWAYS_L;
		case ((1<<yr_key_4)|(1<<yr_AL)): 				printf("KEY_OBSERVATION_ALWAYS_L\n");			return KEY_OBSERVATION_ALWAYS_L;
		case ((1<<yr_key_3)|(1<<yr_AL)): 				printf("KEY_CAMERA_ALWAYS_L\n");				return KEY_CAMERA_ALWAYS_L;
		case ((1<<yr_key_5)|(1<<yr_AL)): 				printf("KEY_RANGING_ALWAYS_L\n");				return KEY_RANGING_ALWAYS_L;
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值