Example:
Initialize anywhere: app_key_init();
void demo(void)
{
bsp_led_toggle(LED0);
}
// The button trigger event will jump to the corresponding function. Here we demonstrate single click to execute the demo function.
button_fun_callback_t button_fun_callback[] = {
{BUTTON0, BUTTIN_SINGLE_CLICK, demo}
};
The file code is as follows
app_key.c
/********************************************************************************
* @file app_key.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-04-03
* @brief key scan
********************************************************************************/
#include #include #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 WHEN != 0 /* Need to be defined in the business layer, the following is an example 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 key scan ********************************************************************************/ #ifndef __APP_KEY_H #define __APP_KEY_H #include #include #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
Previous article:[MCU Framework] [app_led] Using soft timer to implement flashing and breathing lighting modes
Next article:[MCU Framework] Implementation of main file and RTX porting
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- How is the storage period of components calculated?
- The Definitive Guide to FPGA Rapid System Prototyping (Chinese)
- Temperature problems solved for you (IV) Ambient temperature monitoring
- LGA-12 package soldering issues
- [NXP Rapid IoT Review] +3.rapid-iot-studio example bin summary
- GD32E231 Learning 4: External Interrupt EXTI
- The smallest Bluetooth module in the industry? Now available
- Questions about I2C communication
- Unboxing - ESP32-S2-KALUGA-1
- Shanghai ACM32F070 development board evaluation 2, MDK programming environment