【ESP32】按键驱动,长按、短按,可设置多个按键

news/2024/11/26 11:36:16/

文章目录

  • 一、ESP32
  • 二、实现
    • 1.源文件
    • 2.头文件
  • 三、调用
  • 总结


一、ESP32

之后的项目要用到ESP32,对按键驱动进行移植

二、实现

1.源文件

支持短按、长按和多个按键。
我在这里设置了五个按键,如果还有需要可以继续添加,在头文件这里进行修改。

#include "user_key.h"
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"KeyEvent_CallBack_t KeyScanCBS;static void hal_keyConfig(void);static unsigned char hal_getKey1Sta(void);
static unsigned char hal_getKey2Sta(void);
static unsigned char hal_getKey3Sta(void);
static unsigned char hal_getKey4Sta(void);
static unsigned char hal_getKey5Sta(void);
static unsigned char hal_getKey6Sta(void);unsigned char (*getKeysState[KEYNUM])() = {  hal_getKey1Sta,hal_getKey2Sta,hal_getKey3Sta,hal_getKey4Sta,hal_getKey5Sta,hal_getKey6Sta};unsigned char KeyStep[KEYNUM];								//按键检测流程
unsigned short KeyScanTime[KEYNUM];							//去抖延时
unsigned short KeyPressLongTimer[KEYNUM];						//长按延时
unsigned short KeyContPressTimer[KEYNUM];						//连续长按延时	void hal_KeyInit(void)
{unsigned char i;KeyScanCBS = 0;hal_keyConfig();for(i=0; i<KEYNUM; i++){KeyStep[i] = KEY_STEP_WAIT;KeyScanTime[i] = KEY_SCANTIME;KeyPressLongTimer[i] = KEY_PRESS_LONG_TIME;KeyContPressTimer[i] = KEY_PRESS_CONTINUE_TIME;}}void hal_KeyScanCBSRegister(KeyEvent_CallBack_t pCBS)
{if(KeyScanCBS == 0){KeyScanCBS = pCBS;}
}	void hal_KeyProc(void)
{unsigned char i,KeyState[KEYNUM];unsigned char  keys;for(i=0; i<KEYNUM; i++){	keys = 0; KeyState[i] = getKeysState[i]();switch(KeyStep[i]){case KEY_STEP_WAIT:		//等待按键if(KeyState[i]){KeyStep[i] = KEY_STEP_CLICK;	}break;case KEY_STEP_CLICK:				//按键单击按下if(KeyState[i]){if(!(--KeyScanTime[i])){KeyScanTime[i] = KEY_SCANTIME;KeyStep[i] = KEY_STEP_LONG_PRESS;//keys = i+1;										//记录按键ID号//state = KEY_CLICK;								//按键单击按下keys = (i*5)+1;					}}else{KeyScanTime[i] = KEY_SCANTIME;KeyStep[i] = KEY_STEP_WAIT;}break;case KEY_STEP_LONG_PRESS:			//按键长按if(KeyState[i]){	if(!(--KeyPressLongTimer[i])){KeyPressLongTimer[i] = KEY_PRESS_LONG_TIME;KeyStep[i] = KEY_STEP_CONTINUOUS_PRESS;//keys = i+1;										//记录按键ID号//state = KEY_LONG_PRESS;							keys = (i*5)+3;								//长按确认}}else{KeyPressLongTimer[i] = KEY_PRESS_LONG_TIME;KeyStep[i] = KEY_STEP_WAIT;//keys = i+1;										//记录按键ID号//state = KEY_CLICK_RELEASE;						//单击释放keys = (i*5)+2;										//单击释放}break;case KEY_STEP_CONTINUOUS_PRESS:if(KeyState[i]){if(!(--KeyContPressTimer[i])){KeyContPressTimer[i] = KEY_PRESS_CONTINUE_TIME;//keys = i+1;							//持续长按//state = KEY_LONG_PRESS_CONTINUOUS;keys = (i*5)+4;					//持续长按}}else{KeyStep[i] = KEY_STEP_WAIT;KeyContPressTimer[i] = KEY_PRESS_CONTINUE_TIME;keys = i+1;								//记录按键ID号keys = (i*5)+5;								//长按释放}break;}if(keys){if(KeyScanCBS){KeyScanCBS((KEY_VALUE_TYPEDEF)keys);}}}}static void hal_keyConfig(void)
{gpio_pullup_en(K1_PIN);gpio_reset_pin(K1_PIN);gpio_set_direction(K1_PIN,GPIO_MODE_INPUT);// gpio_reset_pin(K2_PIN);// gpio_set_direction(K2_PIN,GPIO_MODE_OUTPUT);// gpio_reset_pin(K3_PIN);// gpio_set_direction(K3_PIN,GPIO_MODE_OUTPUT);// gpio_reset_pin(K4_PIN);// gpio_set_direction(K4_PIN,GPIO_MODE_OUTPUT);// gpio_reset_pin(K5_PIN);// gpio_set_direction(K5_PIN,GPIO_MODE_OUTPUT);// gpio_reset_pin(K6_PIN);// gpio_set_direction(K6_PIN,GPIO_MODE_OUTPUT);}static unsigned char hal_getKey1Sta(void)
{return (!gpio_get_level(K1_PIN));		
} static unsigned char hal_getKey2Sta(void)
{return (!gpio_get_level(K2_PIN));		
}static unsigned char hal_getKey3Sta(void)
{return (!gpio_get_level(K3_PIN));		
}static unsigned char hal_getKey4Sta(void)
{return (!gpio_get_level(K4_PIN));		
}static unsigned char hal_getKey5Sta(void)
{return (!gpio_get_level(K5_PIN));		
}static unsigned char hal_getKey6Sta(void)
{return (!gpio_get_level(K6_PIN));		
}

2.头文件

#ifndef _HAL_KEY_H
#define _HAL_KEY_H//上键
// #define K1_PORT	GPIOB
// #define K1_PIN	GPIO_Pin_3
#define K1_PIN GPIO_NUM_2
#define K2_PIN 0
#define K3_PIN 0
#define K4_PIN 0
#define K5_PIN 0
#define K6_PIN 0// //下键
// #define K2_PORT	GPIOB
// #define K2_PIN	GPIO_Pin_5// //左键
// #define K3_PORT	GPIOB
// #define K3_PIN	GPIO_Pin_6// //右键
// #define K4_PORT	GPIOB
// #define K4_PIN	GPIO_Pin_7// //取消/返回
// #define K5_PORT GPIOB	
// #define K5_PIN	GPIO_Pin_10//确定/设置
// #define K6_PORT GPIOB
// #define K6_PIN	GPIO_Pin_11typedef enum
{KEY_S1,		//上键KEY_S2,		//下键KEY_S3,KEY_S4,KEY_S5,KEY_S6,KEYNUM
}KEY_TYPEDEF;			//按键定义// 按键检测过程
typedef enum
{KEY_STEP_WAIT,			//等待按键KEY_STEP_CLICK,				//按键按下KEY_STEP_LONG_PRESS,				//长按KEY_STEP_CONTINUOUS_PRESS,  			//持续按下
}KEY_STEP_TYPEDEF;typedef enum
{	KEY_IDLE,       	 		 							//按键空闲KEY_CLICK,          								//单击确认KEY_CLICK_RELEASE,            			//单击释放KEY_LONG_PRESS,			   						 	//长按确认KEY_LONG_PRESS_CONTINUOUS,							//长按持续KEY_LONG_PRESS_RELEASE								//长按释放}KEY_EVENT_TYPEDEF;typedef enum
{KEY_IDLE_VAL,KEY1_CLICK,KEY1_CLICK_RELEASE,KEY1_LONG_PRESS,KEY1_LONG_PRESS_CONTINUOUS,KEY1_LONG_PRESS_RELEASE,		//5KEY2_CLICK,								//6KEY2_CLICK_RELEASE,KEY2_LONG_PRESS,KEY2_LONG_PRESS_CONTINUOUS,KEY2_LONG_PRESS_RELEASE,KEY3_CLICK,							//11KEY3_CLICK_RELEASE,KEY3_LONG_PRESS,KEY3_LONG_PRESS_CONTINUOUS,KEY3_LONG_PRESS_RELEASE,KEY4_CLICK,						//16KEY4_CLICK_RELEASE,KEY4_LONG_PRESS,KEY4_LONG_PRESS_CONTINUOUS,KEY4_LONG_PRESS_RELEASE,KEY5_CLICK,						//21KEY5_CLICK_RELEASE,KEY5_LONG_PRESS,KEY5_LONG_PRESS_CONTINUOUS,KEY5_LONG_PRESS_RELEASE,KEY6_CLICK,						//26KEY6_CLICK_RELEASE,KEY6_LONG_PRESS,KEY6_LONG_PRESS_CONTINUOUS,KEY6_LONG_PRESS_RELEASE,}KEY_VALUE_TYPEDEF;typedef void (*KeyEvent_CallBack_t)(KEY_VALUE_TYPEDEF keys);//扫描按键的定时器Tick,以系统Tick(1ms)为单位,10=10ms
#define KEY_SCANT_TICK		10		//10ms//按键消抖时间,以10ms为Tick,2=20ms
#define KEY_SCANTIME	2		//20ms//连续长按时间
#define	KEY_PRESS_LONG_TIME	200	//2s//持续长按间隔时间
#define KEY_PRESS_CONTINUE_TIME	15	//150ms void hal_KeyInit(void);
void hal_KeyProc(void);
void hal_KeyScanCBSRegister(KeyEvent_CallBack_t pCBS);void user_key_task(void *pr);#endif  

三、调用

首先,调用void hal_KeyInit(void)函数,然后需要在应用层实现按键的回调函数static void KeyEventHandle(KEY_VALUE_TYPEDEF keys),当按键被按下之后,将会调用该回调函数。一般可以把蜂鸣器响或者LED闪烁放在这里。

void hal_KeyProc(void)函数需要创建一个定时器放在其中进行执行,推荐使用ESP32的软件定时器。freertos的软件定时器,最小定时的时间要参考systick,只能到ms级别。而ESP32的软件定时器能道us级别。
当然,具体定时器的时间,要根据实际情况设置,如果是对按键反应时间要求比较高的场合,比如说秒表,计时器,要显示精准,那就可以将时间设置短一些。
如果对按键反应时间要求不高,就可以设置长一些,少消耗一些cpu资源。

//按键回调函数
static void KeyEventHandle(KEY_VALUE_TYPEDEF keys)
{if((keys==KEY1_CLICK)|| (keys==KEY2_CLICK)|| (keys==KEY3_CLICK)|| (keys==KEY4_CLICK)|| (keys==KEY5_CLICK)|| (keys==KEY6_CLICK)){printf("key1::key_CLICK%d",keys);//LedMsgInput(LED1,LED_LIGHT_100MS,1);printf("beep is sound\n");//hal_Oled_ClearArea(16,20,128,30);//OLED_ShowString(16,20,(uint8_t*)"key_CLICK",16,1);//OLED_Refresh();//LedMsgInput(LED1,LED_LIGHT,1);}else if((keys==KEY1_CLICK_RELEASE)|| (keys==KEY2_CLICK_RELEASE)|| (keys==KEY3_CLICK_RELEASE)|| (keys==KEY4_CLICK_RELEASE)|| (keys==KEY5_CLICK_RELEASE)|| (keys==KEY6_CLICK_RELEASE)){printf("key1::CLICK_RELEASE%d",keys);//LedMsgInput(LED1,LED_BLINK4,1);}else if((keys==KEY1_LONG_PRESS)|| (keys==KEY2_LONG_PRESS)|| (keys==KEY3_LONG_PRESS)|| (keys==KEY4_LONG_PRESS)|| (keys==KEY5_LONG_PRESS)|| (keys==KEY6_LONG_PRESS)){printf("key1::LONG_PRESS%d",keys);//LedMsgInput(LED1,LED_DARK,1);}
}//软件定时器回调函数
static void periodic_timer_callback(void* arg)
{//int64_t time_since_boot = esp_timer_get_time();hal_KeyProc();//ESP_LOGI("example", "Periodic timer called, time since boot: %lld us", time_since_boot);
}

总结

ESP-IDF example中也提供了相应的例程,相对更加完善


http://www.ppmy.cn/news/453415.html

相关文章

iOS设置键盘上Return按键及点击操作

想要修该iOS键盘上Return按钮的样式变为搜索&#xff0c;并且监听它被点击了&#xff0c;做出响应&#xff0c; 先设置Return按键的样式&#xff0c; textField.returnKeyType UIReturnKeySearch;//变为搜索按钮 textField.delegate self;//设置代理 在代理方法中实现你想要…

键盘的相关设置

一、键盘风格 UIKit框架支持8种风格键盘。 typedef enum { UIKeyboardTypeDefault, // 默认键盘&#xff1a;支持所有字符 UIKeyboardTypeASCIICapable, // 支持ASCII的默认键盘 UIKeyboardTypeNumbersAndPunctuation, // 标准电话键盘&a…

android 按键 设置在哪,如何在Android设备上设置按键和按键?

OnKeyUp 和; OnKeyDown 事件不会影响它,因为软键盘几乎不会发出这些声音。 这是一个粗略的原型,它根据预期的字符串过滤字符输入。有很多改进空间;虽然自定义实现仍然比尝试使用框架方法更好,但它可能只捕获 艾斯 关键…这个 FilteredEditText 捕捉任何输入 之前 它可能出现在屏…

键盘按键值

按键值按键码 退格键VK_BACK (8)ESC 键VK_ESCAPE (27)TAB 键VK_TAB (9)Caps Lock 键VK_CAPITAL (20)Shift 键VK_SHIFT ($10)空格键VK_SPACE ($20/32)回车键VK_RETURN (13)左徽标键VK_LWIN (91)Ctrl 键VK_CONTROL (17)右徽标键 VK_LWIN (92) Alt 键VK_MENU (18)鼠标右键快捷键VK…

html如何设置自动点击,按键精灵怎么设置自动点击

1.首先打开【按键精灵】&#xff0c;再打开的主界面左侧找到【快速向导】&#xff0c;并且单击它。 2.在打开的界面&#xff0c;找到【鼠标左键连点器】选项&#xff0c;并且双击打开它。 3.这样就打开了这个命令的脚本&#xff0c;在界面的左侧找到并且单击【鼠标命令】选项。…

ubuntu中通过logiops设置罗技鼠标按键

Logitech Options 是罗技办公鼠标的自定义功能驱动&#xff0c;但是只提供了Windows和Mac版本。在Linux环境下进行鼠标按键的配置可以使用第三方驱动项目&#xff1a;logiops项目地址 安装 参考官网教程https://github.com/PixlOne/logiops#readme 依赖&#xff1a; 项目需要…

安卓按键设置样式

精彩博文: https://blog.csdn.net/tracydragonlxy/article/details/88552262 1.右键drawable文件夹新建Android XML File 文件&#xff0c;命名为btn_normal.xml&#xff0c;复制粘贴以下代码 <?xml version"1.0" encoding"utf-8"?> <shapexm…

QT 按键样式设置

开发的QT程序的时候&#xff0c;按键效果一般都会自己写&#xff0c;按下和释放的效果以及按键被禁用的效果&#xff0c;直接上程序吧&#xff0c;不同的控件样式表的内容应该不一样&#xff0c;网上找了很久没有找到QT的样式说明&#xff0c;哪位朋友找到了还望不吝赐教&#…