简介:
按键检测在嵌入式开发中经常会被使用,在一些独立按键比较少的情况下时要处理多个按键事件的话经常会通过单击按键/双击按键 及长按按键的处理方式来响应按键动作,在网上浏览时看到EmbeddedButton(EmbeddedButton 移植适配:
移植适配相对很容易,只有embedded_button.c 一个文件加入到工程编译即可,使用方法在github 上有描述我们,我们参照对应的代码使用即可,需要依赖我们自己实现的主要有以下内容,注册按键按键的call back 事件,及对应的事件的回调处理函数。
rt_pin_mode(PM580_SWA_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PM580_SWB_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PM580_SWX_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PM580_SWY_PIN, PIN_MODE_INPUT_PULLUP); button_init(&buttona_up, read_button_pin, 0, btna_id, buttona_up_map, ARRAY_SIZE(buttona_up_map)); button_start(&buttona_up); button_init(&buttonb_down, read_button_pin, 0, btnb_id, buttonb_down_map, ARRAY_SIZE(buttonb_down_map)); button_start(&buttonb_down); button_init(&buttonx_left, read_button_pin, 0, btnx_id, buttonx_left_map, ARRAY_SIZE(buttonx_left_map)); button_start(&buttonx_left); button_init(&buttony_right, read_button_pin, 0, btny_id, buttony_right_map, ARRAY_SIZE(buttony_right_map)); button_start(&buttony_right);
本次注册了四个按键,本地配置通过其中一个按键控制LED 亮度,控制LED 亮度前我们需要初始化配置PWM通道。从 raspberry-pico 的原理图可以知道LED 接在 PIO25 的pin脚上,对应的引脚可以配置为PWM4 CHANNELB
#include <string.h> #include <stdlib.h> #include <ctype.h> #include <finsh.h> #include <msh_parse.h> static void _led_pwm(int argc, char *argv[]) { static uint slice_num; if(argc < 2) { return ; } if (0 == rt_strcmp("pwm", argv[1])) { uint8_t pwm_value = atoi(argv[2]); pwm_set_chan_level(slice_num, PWM_CHAN_B, pwm_value); } else if (0 == rt_strcmp("init", argv[1])) { // PWM Config gpio_set_function(25, GPIO_FUNC_PWM); slice_num = pwm_gpio_to_slice_num(25); pwm_set_wrap(slice_num, 100); pwm_set_chan_level(slice_num, PWM_CHAN_B, 1); pwm_set_clkdiv(slice_num,50); pwm_set_enabled(slice_num, true); } else { return; } } MSH_CMD_EXPORT_ALIAS(_led_pwm, led, led [option]);
初始化好PWM 通道后,我么可以继续配置EmbeddedButton ,该框架以来我们实现对应按键的读取函数,对应代码如下:
uint8_t read_button_pin(uint8_t button_id) { uint8_t id; switch(button_id) { case btna_id: id = PM580_SWA_PIN; break; case btnb_id: id = PM580_SWB_PIN; break; case btnx_id: id = PM580_SWX_PIN; break; case btny_id: id = PM580_SWY_PIN; break; default: break; } return rt_pin_read(id); }
还依赖我们可以配置按键的回调函数处理,我们配置单击,双击,及长按下及释放处理逻辑,添加如下回调处理函数。
void single_click_handle1(void* btn) { rt_kprintf("single click pwm 50%\n"); pwm_set_chan_level(slice_num, PWM_CHAN_B, 50); } void single_click_handle2(void* btn) { rt_kprintf("double click pwm 80%\n"); pwm_set_chan_level(slice_num, PWM_CHAN_B, 80); } void single_click_handle3(void* btn) { rt_kprintf("long click start pwm 100%\n"); pwm_set_chan_level(slice_num, PWM_CHAN_B, 100); } void single_click_handle4(void* btn) { rt_kprintf("long click end pwm 0%\n"); pwm_set_chan_level(slice_num, PWM_CHAN_B, 0); } const key_value_match_map_t buttonx_left_map[] = { { .tar_result = SINGLE_CLICK_KV, .kv_func_cb = single_click_handle1 }, { .tar_result = DOUBLE_CLICK_KV, .kv_func_cb = single_click_handle2 }, { .tar_result = LONG_PRESEE_START, .kv_func_cb = single_click_handle3 }, { .tar_result = LONG_PRESEE_HOLD_END, .kv_func_cb = single_click_handle4 }, };
EmbeddedButton 周期监检查按键状态需要我button_tick()ton_tick()接口来更新按键状态
while (1) { button_ticks(); rt_thread_mdelay(GAME_REFRESH_TIME_BASE); }
按键的去抖动及一些参数配置也可以根据自己的实际需求来进行配置,本地使用配置如下:
//According to your need to modify the constants. #define TICKS_INTERVAL 5 //ms #define DEBOUNCE_TICKS 2 //MAX 16 #define SHORT_TICKS (50 /TICKS_INTERVAL) #define LONG_TICKS (1000 /TICKS_INTERVAL)
运行单击按键,及双击 长按 事件都可以按照预期响应,对应的LED 的亮度也跟随变化。
总结
EmbeddedButton 还短按后长按等事件的处理,相对按键的处理模式足够工作中使用,如果要使用按键的话该框架支持的功能还是比较丰富的,相对代码量也不大很适合嵌入式开发场景使用。