头文件,bsp_key.h
#define KEY_NUM 2 //按键数量
typedef enum{
KEY1_RELEASE = 0x00,
KEY1_LONGCLICKED,
KEY1_LONGLONG,
KEY1_MULTICLICKED_1,
KEY1_MULTICLICKED_2,
KEY1_MULTICLICKED_3,
KEY1_MULTICLICKED_4,
KEY1_MULTICLICKED_5,
KEY2_RELEASE,
KEY2_LONGCLICKED,
KEY2_LONGLONG,
KEY2_MULTICLICKED_1,
KEY2_MULTICLICKED_2,
KEY2_MULTICLICKED_3,
KEY2_MULTICLICKED_4,
KEY2_MULTICLICKED_5,
};
#define LONG_PRESS_THRESHOLD 1000 //长长按时间
#define IDLE_COUNT_THRESHOLD 200 //空闲时间
#define CLICK_LONG_THRESHOLD 500 //长按时间
#define CLICK_COUNT_MAX 1500
#define CONFIRM_COUNT 25 //消抖时间
typedef struct{
int (*Scan)(void);
void (*Init)(void);
uint16_t KeyCnt;
uint8_t IdleCnt;
uint8_t ClickCnt;
uint8_t LongPressed;
uint8_t State;
}Key_t;
通过修改头文件中的宏定义可以修改按键检测的参数。
源文件,bsp_key.c
定义按键对象
Key_t g_Key_List[KEY_NUM];
初始化代码
/************************************* USER CODE *************************************/
/*
*********************************************************************************************************
* 函 数 名: Key1_Scan
* 功能说明: 扫描按键1的状态
* 形 参: 无
* 返 回 值: 按键1的状态
*********************************************************************************************************
*/
static int Key1_Scan(void)
{
return gpio_get_level(9);
}
/*
*********************************************************************************************************
* 函 数 名: Key2_Scan
* 功能说明: 扫描按键2的状态
* 形 参: 无
* 返 回 值: 按键2的状态
*********************************************************************************************************
*/
static int Key2_Scan(void)
{
return gpio_get_level(2);
}
/*
*********************************************************************************************************
* 函 数 名: Key1_Init
* 功能说明: 初始化按键1的配置
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void Key1_Init(void)
{
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE, //falling edge interrupt
.mode = GPIO_MODE_INPUT, //set as input mode
.pin_bit_mask = 1<<GPIO_NUM_9, //bit mask of the pins GPIO9
.pull_down_en = 0, //disable pull-down mode
.pull_up_en = 1 //enable pull-up mode
};
//configure GPIO with the given settings
gpio_config(&io_conf);
}
/*
*********************************************************************************************************
* 函 数 名: Key2_Init
* 功能说明: 初始化按键2的配置
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void Key2_Init(void)
{
gpio_config_t io_conf2 = {
.intr_type = GPIO_INTR_DISABLE, //falling edge interrupt
.mode = GPIO_MODE_INPUT, //set as input mode
.pin_bit_mask = 1<<GPIO_NUM_2, //bit mask of the pins GPIO9
.pull_down_en = 0, //disable pull-down mode
.pull_up_en = 1 //enable pull-up mode
};
//configure GPIO with the given settings
gpio_config(&io_conf2);
}
/************************************* END *************************************/
/*
*********************************************************************************************************
* 函 数 名: bsp_Key_Init
* 功能说明: 初始化按键列表,设置扫描和初始化函数指针,初始化按键状态和计数器
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Key_Init(void)
{
g_Key_List[0].Scan = Key1_Scan;
g_Key_List[0].Init = Key1_Init;
g_Key_List[1].Scan = Key2_Scan;
g_Key_List[1].Init = Key2_Init;
for (uint8_t i = 0; i < KEY_NUM; i++)
{
g_Key_List[i].KeyCnt = 0;
g_Key_List[i].IdleCnt = 0;
g_Key_List[i].ClickCnt = 0;
g_Key_List[i].LongPressed = 0;
g_Key_List[i].State = 0;
}
g_Key_List[0].Init();
g_Key_List[1].Init();
}
按键扫描代码:
/*
*********************************************************************************************************
* 函 数 名: bsp_key_scan
* 功能说明: 扫描按键状态,处理长按、短按和松手事件
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_key_scan(void)
{
uint8_t KeyVal = 0x00;
for(uint8_t i = 0; i < KEY_NUM; i++)
{
if (g_Key_List[i].Scan() == 0)
{
if (g_Key_List[i].KeyCnt < CLICK_COUNT_MAX)
g_Key_List[i].KeyCnt++;
/* 长长按 */
if (g_Key_List[i].KeyCnt > LONG_PRESS_THRESHOLD && !g_Key_List[i].LongPressed)
{
KeyVal = i * 8 + KEY1_LONGLONG;
g_Key_List[i].State = KeyVal;
// printf("长长按, KeyVal = 0x%x\r\n", KeyVal);
xQueueSend(gpio_evt_queue, &KeyVal, NULL);
g_Key_List[i].LongPressed = 1;
g_Key_List[i].KeyCnt = 0;
}
g_Key_List[i].IdleCnt = 0;
}
else
{
/* Release */
if (g_Key_List[i].State != i*8)
{
if (g_Key_List[i].KeyCnt == 0)
{
KeyVal = i * 8;
g_Key_List[i].State = i*8;
xQueueSend(gpio_evt_queue, &KeyVal, NULL);
// printf("Release\r\n");
}
else
g_Key_List[i].KeyCnt--;
}
if (g_Key_List[i].LongPressed)
{
g_Key_List[i].KeyCnt = 0;
g_Key_List[i].LongPressed = 0;
g_Key_List[i].ClickCnt = 0;
}
/* 单击、多击松手 */
if (g_Key_List[i].IdleCnt++ >= IDLE_COUNT_THRESHOLD)
{
g_Key_List[i].KeyCnt = 0;
if (g_Key_List[i].ClickCnt)
{
KeyVal = i * 8 + KEY1_MULTICLICKED_1 - 1 + g_Key_List[i].ClickCnt;
g_Key_List[i].State = KeyVal;
xQueueSend(gpio_evt_queue, &KeyVal, NULL);
// printf("按键%d击, KeyVal = 0x%x\r\n",g_Key_List[i].ClickCnt,KeyVal);
}
g_Key_List[i].ClickCnt = 0;
g_Key_List[i].IdleCnt = 0;
}
/* long Press */
if (g_Key_List[i].KeyCnt > CLICK_LONG_THRESHOLD)
{
KeyVal = i * 8 + KEY1_LONGCLICKED;
g_Key_List[i].State = KeyVal;
xQueueSend(gpio_evt_queue, &KeyVal, NULL);
g_Key_List[i].KeyCnt = 0;
// printf("按键长按, KeyVal = 0x%x\r\n", KeyVal);
g_Key_List[i].ClickCnt = 0;
}
/* 单击、多击 */
else if (g_Key_List[i].KeyCnt <= CLICK_LONG_THRESHOLD && g_Key_List[i].KeyCnt >= CONFIRM_COUNT)
{
g_Key_List[i].ClickCnt++;
g_Key_List[i].KeyCnt = 0;
}
}
}
}
代码中使用 xQueueSend(gpio_evt_queue, &KeyVal, NULL) 发送键值至其他线程,在裸机中使用可以替换为向自己的队列FIFO写键值。
示例:
扫描线程,周期2ms,在裸机环境中可使用systick定时器,在systick中断中调用bsp_key_scan函数。
void key_task_example(void* arg)
{
for(;;)
{
bsp_key_scan();
vTaskDelay(2);
}
}
static void gpio_task_example(void* arg)
{
uint32_t KeyVal;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &KeyVal, portMAX_DELAY))
{
switch (KeyVal)
{
case KEY1_RELEASE :
printf("Release\r\n");
break;
case KEY1_LONGCLICKED :
printf("KEY1_LONGCLICKED\r\n");
break;
case KEY1_LONGLONG :
printf("KEY1_LONGLONGCLICKED\r\n");
break;
case KEY1_MULTICLICKED_1 :
printf("KEY1_MULTICLICKED_1\r\n");
break;
case KEY1_MULTICLICKED_2 :
printf("KEY1_MULTICLICKED_2\r\n");
break;
case KEY1_MULTICLICKED_3 :
printf("KEY1_MULTICLICKED_3\r\n");
break;
case KEY1_MULTICLICKED_4 :
printf("KEY1_MULTICLICKED_4\r\n");
break;
case KEY1_MULTICLICKED_5 :
printf("KEY1_MULTICLICKED_5\r\n");
break;
default: break;
}
}
}
}
运行结果:

7944






