LVGL V9增加实体按键 驱动层和应用层的处理

最近因为工作,也在学习了一些关于LVGL的内容,整体环境目前是:一个单片机,外接一个屏幕,目前屏幕是已经点亮和有触摸;但还希望在这个为基础,增加一些按键控制的环节,比如上下左右,进入返回这些的操作,所以有了这篇文章;

此贴目的:基于LVGL V9版本,在驱动层注册键盘keypad,初始化,将想要的引脚接口配置好,读到他的GPIO电平,当按键被按下后,触发,然后再讲这个值传输到上层AP层,AP层的UI做出相对应的反应。

以下为驱动层方面的处理:

做一个整体去初始化设备的函数lv_port_indev_init,在这个函数中对keypad做初始化和注册键盘,读取键盘的处理;

C 复制代码
void lv_port_indev_init(void)
{
	//此处只用键盘初始化做示例,如果对其他IO设备有需求的话,也可以增加,例如:鼠标,encoder,touchpad等
    keypad_init();
    indev_keypad = lv_indev_create();
    lv_indev_set_type(indev_keypad, LV_INDEV_TYPE_KEYPAD);
    lv_indev_set_read_cb(indev_keypad, keypad_read);
}

后续在keypad初始化中,对想要的GPIO口进行相应的处理:

C 复制代码
#define KEY_PIN1     "PD.2"

static void keypad_init(void)
{
    static u32 pin = 0;
    pin = gpio_pin_check(KEY_PIN1, GPIO_SET_MODE_FLAG);

    rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP);

    rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING_FALLING,
                      gpio_input_irq_handler, &pin);

    rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
}

当然,不可或缺的还有keypad_read

C 复制代码
static void keypad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
{
    static uint32_t last_key = 0;
    /*Get whether the a key is pressed and save the pressed key*/
    uint32_t act_key = keypad_get_key();
    if(act_key != 0) {
        data->state = LV_INDEV_STATE_PR;

        /*Translate the keys to LVGL control characters according to your key definitions*/
        switch(act_key) {
            case 1:
                act_key = LV_KEY_DOWN;
                break;
            case 2:
                act_key = LV_KEY_UP;
                break;
            case 3:
                act_key = LV_KEY_LEFT;
                break;
            case 4:
                act_key = LV_KEY_RIGHT;
                break;
            case 5:
                act_key = LV_KEY_ENTER;
                break;
        }

        last_key = act_key;
    }
    else {
        data->state = LV_INDEV_STATE_REL;
    }
    data->key = last_key;
}

随后的话,在get key的函数中也要做相对应的处理,实际上这些都是环环相扣的,初始化中会包含读,读中又包含获取,才能相对应上

C 复制代码
/*Get the currently being pressed key.  0 if no key is pressed*/
static uint32_t keypad_get_key(void)
{
    /*Your code comes here*/
    static uint8_t last_key = 0;
    uint8_t current_key = 0;
    if (key_trigger == 1) {
        key_trigger = 0;
        current_key = 1;  
    }

    if(current_key != 0) {
        last_key = current_key;
        return current_key;
    }
    
    return 0;
}

后续的话就是需要在应用层做处理,在keypad_read中已经把值返回到对应的LV_KEY_DOWN/LV_KEY_UP/LV_KEY_LEFT/LV_KEY_RIGHT,故在应用层中比较重要的就是需要去获取这个key,其中的步骤我们一步步来:

1、需要有一个lv_group_t *menu_group,并增加初始化;

C 复制代码
static lv_group_t *menu_group;

void lv_init_group()
{
    menu_group = lv_group_create();

    lv_group_set_editing(menu_group, false);
    lv_indev_set_group(indev_keypad,menu_group);
}

2、在你的组中增加obj,例如把btn加进这个group中;

C 复制代码
lv_group_add_obj(menu_group,btn);

3、给你的btn增加需要动的操作,并且增加focus属性!(最重要,没有这个属性将不会有任何响应)

然后才是对这个focus进行移动,例如lv_group_focus_next

C 复制代码
lv_obj_add_event_cb(btn, menu_key_cb, LV_EVENT_KEY, NULL);

lv_group_focus_obj(current_selected_btn); // 给当前选中的按钮增加focus

static void menu_key_cb(lv_event_t *e)
{
    lv_event_code_t event_code = lv_event_get_code(e);
    lv_obj_t * target = lv_event_get_target(e);

    printf("get_key :%d\n", event_code);
    if (event_code == LV_KEY_LEFT)
    {
        lv_group_focus_next(menu_group);
    }

}

4、最后就是大功告成,可以看到效果了!

总结:

整体的LVGL功能其实不难,但就是有几个需要注意的点,例如:必须把输入设备绑定 group、需要把按钮加入进group、按钮还需要增加focus、回调属性(类似qt的信号槽);

相关推荐
The_superstar63 天前
衡山派D133EBS入门笔记
笔记·python·c·衡山派·小曹越
charlie1145141913 天前
嵌入式Linux驱动开发(8)——内存映射 I/O - 别拿物理地址当指针用
linux·开发语言·驱动开发·c·imx6ull
邪修king3 天前
C++ 模板进阶超全攻略:非类型模板参数、模板特化、分离编译与避坑指南
开发语言·c++·c
charlie1145141914 天前
嵌入式Linux驱动开发(7) 从虚拟设备到真实硬件 —— LED驱动硬件基础
linux·开发语言·驱动开发·内核·c
xzl044 天前
LVGL 启动流程全解析:RT-Thread 下的界面渲染链路
rt-thread·lvgl
xzl044 天前
LVGL Coffee UI 接入实战:问题解决全记录
ui·rt-thread·lvgl
charlie1145141916 天前
通用GUI编程技术——图形渲染实战(三十六)——Constant Buffer与数据传递:CPU-GPU通信通道
开发语言·c++·windows·c·图形渲染·win32
17岁boy想当攻城狮8 天前
GlibC 在线程里引发use-after-free退出时才崩溃原因与分析
c·glibc
少司府9 天前
C++基础入门:初识模板
开发语言·c++·c·模板·函数模板·类模板·泛型编程