使用例子:
任意地点初始化:app_key_init();
void demo(void)
{
bsp_led_toggle(LED0);
}
// 按键触发事件则会跳转到对应功能函数。 这里演示单击,执行demo函数。
button_fun_callback_t button_fun_callback[] = {
{BUTTON0, BUTTIN_SINGLE_CLICK, demo}
};
文件代码如下
app_key.c
/********************************************************************************
* @file app_key.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-04-03
* @brief 按键扫描
********************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include "os_api.h"
#include "bsp_key.h"
#include "app_key.h"
#include "business_gpio.h"
#include "business_function.h"
#define KEYN BS_BUTTONn
#define KEY_SCAN_CYCLE_MS BS_BUTTON_SCAN_CYCLE_MS
#define KEY_RELEASE_TIME BS_BUTTON_RELEASE_TIME
#define KEY_SINGLE_CLICK_TIME BS_BUTTON_SINGLE_CLICK_TIME
#define KEY_DOUBLE_CLICK_TIME BS_BUTTON_DOUBLE_CLICK_TIME
#define KEY_LONG_PRESS_TIME BS_BUTTON_LONG_PRESS_TIME
#define KEY_LONG_LONG_PRESS_TIME BS_BUTTON_LONG_LONG_PRESS_TIME
typedef enum
{
KEY_RELEASE = 0,
KEY_PRESS
} button_flag_t;
typedef enum
{
KEY_NULL = 0,
KEY_ONE_PRESS,
KEY_TWO_PRESS
} button_times_t;
typedef struct
{
uint16_t press_time;
uint16_t release_time;
button_flag_t flag;
button_times_t press_times;
button_event_t event;
} button_state_t;
static const uint8_t g_key_press_state[KEYN] = {
#if (KEYN > 0)
BS_BUTTON0_PRESS_LEVEL
#endif
#if (KEYN > 1)
,BS_BUTTON1_PRESS_LEVEL
#endif
#if (KEYN > 2)
,BS_BUTTON2_PRESS_LEVEL
#endif
#if (KEYN > 3)
,BS_BUTTON3_PRESS_LEVEL
#endif
};
#if KEYN != 0
/* 需要在业务层进行定义,下方是例子
void demo(void)
{
bsp_led_toggle(LED0);
}
button_fun_callback_t button_fun_callback[] = {
{BUTTON0, BUTTIN_SINGLE_CLICK, demo}
};
*/
extern const button_fun_callback_t button_fun_callback[];
static button_state_t button_state[KEYN];
static void timer_key_scan(void const *arg);
static os_timer_id key_scan_id;
static uint32_t timer_ret;
static os_timer_def(k_scan, timer_key_scan);
static uint8_t scan_key(void)
{
uint8_t sign = BUTTIN_NULL;
uint8_t times = 0;
for (uint8_t i = 0; i < KEYN; i++)
{
if (bsp_button_get_state((bsp_button_t)i) == (uint8_t)g_key_press_state[i])
{
button_state[i].press_time++;
button_state[i].release_time = 0;
if (button_state[i].press_time >= 0xFFFD)
{
button_state[i].press_time = 0xFFFD;
}
if (button_state[i].flag == KEY_RELEASE)
{
if (button_state[i].press_times == KEY_NULL)
{
button_state[i].press_times = KEY_ONE_PRESS;
button_state[i].event = BUTTIN_PRESS;
sign = 1;
continue;
}
else if (button_state[i].press_times == KEY_ONE_PRESS &&
button_state[i].press_time >= (KEY_SINGLE_CLICK_TIME / KEY_SCAN_CYCLE_MS) &&
button_state[i].press_time < (KEY_LONG_PRESS_TIME / KEY_SCAN_CYCLE_MS))
{
button_state[i].press_times = KEY_TWO_PRESS;
button_state[i].event = BUTTIN_TWO_PRESS;
sign = 1;
continue;
}
}
button_state[i].flag = KEY_PRESS;
if (button_state[i].press_time == (KEY_LONG_PRESS_TIME / KEY_SCAN_CYCLE_MS))
{
button_state[i].event = BUTTIN_LONG_PRESS;
button_state[i].press_times = KEY_NULL;
sign = 2;
continue;
}
else if (button_state[i].press_time == (KEY_LONG_LONG_PRESS_TIME / KEY_SCAN_CYCLE_MS))
{
button_state[i].event = BUTTIN_LONG_LONG_PRESS;
button_state[i].press_times = KEY_NULL;
sign = 3;
continue;
}
}
else
{
button_state[i].release_time++;
if (button_state[i].press_times == KEY_ONE_PRESS &&
button_state[i].release_time == (KEY_RELEASE_TIME / KEY_SCAN_CYCLE_MS))
{
button_state[i].press_time = 0;
button_state[i].event = BUTTIN_SINGLE_CLICK;
sign = 1;
continue;
}
else if (button_state[i].press_times == KEY_TWO_PRESS &&
button_state[i].release_time == (KEY_DOUBLE_CLICK_TIME / KEY_SCAN_CYCLE_MS))
{
button_state[i].press_time = 0;
button_state[i].press_times = KEY_ONE_PRESS;
button_state[i].event = BUTTIN_DOUBLE_CLICK;
sign = 1;
continue;
}
else if (button_state[i].release_time > (KEY_RELEASE_TIME / KEY_SCAN_CYCLE_MS))
{
button_state[i].press_time = 0;
button_state[i].press_times = KEY_NULL;
button_state[i].event = BUTTIN_NULL;
}
button_state[i].flag = KEY_RELEASE;
if(button_state[i].release_time == 1)
{
button_state[i].event = BUTTIN_RELEASE;
sign = 1;
continue;
}
if (button_state[i].release_time > 0xFD)
{
button_state[i].release_time = 0xFD;
times ++;
if (times == KEYN)
{
app_key_scan_stop();
}
}
}
}
return sign;
}
static void key_run_callback(uint8_t ch, uint8_t event)
{
for (uint8_t i = 0; i < 255; i++)
{
if (button_fun_callback[i].key_ch == 0xFF)
{
return;
}
if (button_fun_callback[i].key_ch == ch && button_fun_callback[i].event == event)
{
if ((button_fun_callback[i].callback) != NULL)
{
(button_fun_callback[i].callback)();
}
}
}
}
static void timer_key_scan(void const *arg)
{
if (scan_key() != 0)
{
for (uint8_t i = 0; i < BS_BUTTONn; i++)
{
switch (button_state[i].event)
{
case BUTTIN_NULL:
break;
case BUTTIN_RELEASE:
key_run_callback(i, BUTTIN_RELEASE);
break;
case BUTTIN_PRESS:
key_run_callback(i, BUTTIN_PRESS);
break;
case BUTTIN_TWO_PRESS:
key_run_callback(i, BUTTIN_TWO_PRESS);
break;
case BUTTIN_SINGLE_CLICK:
key_run_callback(i, BUTTIN_SINGLE_CLICK);
break;
case BUTTIN_DOUBLE_CLICK:
key_run_callback(i, BUTTIN_DOUBLE_CLICK);
break;
case BUTTIN_LONG_PRESS:
key_run_callback(i, BUTTIN_LONG_PRESS);
break;
case BUTTIN_LONG_LONG_PRESS:
key_run_callback(i, BUTTIN_LONG_LONG_PRESS);
break;
default:
break;
}
button_state[i].event = BUTTIN_NULL;
}
}
}
bool app_key_init(void)
{
key_scan_id = os_timer_create(os_timer(k_scan), OS_TIMER_PERIODIC, &timer_ret);
if (!key_scan_id)
{
return false;
}
return true;
}
bool app_key_scan_start(void)
{
if (os_timer_start(key_scan_id, KEY_SCAN_CYCLE_MS) != OS_OK)
{
return false;
}
return true;
}
bool app_key_scan_stop(void)
{
if (os_timer_stop(key_scan_id) != OS_OK)
{
return false;
}
return true;
}
#else
bool app_key_init(void)
{
return false;
}
bool app_key_scan_start(void)
{
return false;
}
bool app_key_scan_stop(void)
{
return false;
}
#endif
app_key.h
/********************************************************************************
* @file app_key.h
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-04-03
* @brief 按键扫描
********************************************************************************/
#ifndef __APP_KEY_H
#define __APP_KEY_H
#include <stdint.h>
#include <stdbool.h>
#include "bsp_key.h"
typedef enum
{
BUTTIN_NULL = 0,
BUTTIN_RELEASE,
BUTTIN_PRESS,
BUTTIN_TWO_PRESS,
BUTTIN_SINGLE_CLICK,
BUTTIN_DOUBLE_CLICK,
BUTTIN_LONG_PRESS,
BUTTIN_LONG_LONG_PRESS,
} button_event_t;
typedef void(*bsp_button_callback)(void);
typedef struct
{
uint8_t key_ch;
button_event_t event;
bsp_button_callback callback;
} button_fun_callback_t;
bool app_key_init(void);
bool app_key_scan_start(void);
bool app_key_scan_stop(void);
#endif