首页 > 其他分享 >[单片机框架][APP_KEY] 利用软定时器实现按键扫描

[单片机框架][APP_KEY] 利用软定时器实现按键扫描

时间:2022-10-31 23:32:32浏览次数:53  
标签:KEY APP BUTTIN 单片机 state key PRESS button


使用例子:

任意地点初始化: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


标签:KEY,APP,BUTTIN,单片机,state,key,PRESS,button
From: https://blog.51cto.com/xuejianqiang/5811398

相关文章