记录开发过程中的问题和功能。毕se代做,小家电开发。 收徒带做企业级项目,帮助毕业生和转行人员顺利找到工作。

LiSun

记录开发过程中的问题和功能。毕se代做,小家电开发。 收徒带做企业级项目,帮助毕业生和转行人员顺利找到工作。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

使用例子:

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

posted on 2022-08-13 11:00  嵌入式单片机实验室  阅读(83)  评论(0)    收藏  举报
记录开发过程中的问题和功能。毕se代做,小家电开发。 收徒带做企业级项目,帮助毕业生和转行人员顺利找到工作。