lvgl8.x 对接实体按键驱动

这篇具有很好参考价值的文章主要介绍了lvgl8.x 对接实体按键驱动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. lvgl 输入设备种类

实体按键属于 lvgl 的输入设备中的一种,所以对接外部的硬件实体按键实际上就是为 lvgl 添加输入设备。为 lvgl 添加输入设备需要在 lv_port_indev.c 这个 c 文件中完成,注意这个文件并不存在于 lvgl src 源码文件夹下,而是位于 examples/porting 文件夹下,在这个目录下官方为我们准备好了对接模板文件,我们对这个模板文件进行修改即可

lvgl 的输入设备共有以下五种:
Touchpad 触摸板,例如电容屏、电阻屏等
Mouse 鼠标
Keypad 键盘
Encoder 编码器
Button 外部按键

开发板目前现有的驱动是 ButtonKeypad 这两者其实都是外部或是说显示屏周边的按键,两者的的区别是,Button 属于独立按键而 Keypad 属于矩阵键盘。

2. lvgl 接入 Button 按键

**Button 按键特殊注意点:**在 lvgl 的设计思想上 Button 按键用于在没有触摸屏的情况下,为了点触软件按钮,而设计的与软件按钮对应的周边(比如硬件按钮位于软件按钮正上方,正下方,左方或右方)硬件实体按键。

**Button 按键如何工作呢:**通过 lvgl 的设计可以不难发现 lvgl 并没有把 Button 按键单纯作为一个按键,而是将软件按键一一对应的实体按键点按产生的电平变化转化为在屏幕某一个坐标上的点按,换句话说 lvglButton 按键模拟成了触摸屏,而模拟点按的坐标就是你想控制的那个软件按键在屏幕上显示的中心坐标(注意中心坐标需要我们根据我们要控制的软件按键坐标自行计算好,并提供给 lvgl,我们计算的坐标必须位于软件按键的中心,不然会发现无法控制,软件按键不会随硬件按键按下而跟着按下)。

所以按钮是指屏幕旁边的外部 硬件 按钮,它们被分配给屏幕的特定坐标。如果一个按钮被按下,它将模拟在指定坐标上的按下。(类似于触摸板)将按钮分配给坐标使用
lv_indev_set_button_points(my_indev,points_array)points_array 应该像下面这样:

static const lv_point_t btn_points[4] = {
    {54,  226},
    {124, 226},
    {194, 226},
    {264, 226},
};

2.1 修改输入设备初始化函数

lvgl 实体按键,LVGL8.X,stm32,lvgl8.0,lvgl按键驱动,lvgl
因为这里需要对接的是 Button 按键(独立按键),所以我们将 lv_port_indev.c 模板文件中
void lv_port_indev_init() 初始化函数与 Button 按键无相关的内容(比如触摸屏,鼠标,编码器等)先注释(或使用条件编译进行隔离编译),留下需要的 Button 按键部分,如下图所示。
lvgl 实体按键,LVGL8.X,stm32,lvgl8.0,lvgl按键驱动,lvgl

  • button_init(); 这个函数可以用于编写按键相关的硬件 IO 初始化相关代码,如果硬件 IO 初始化已经在专门统一的驱动中已经初始化,这个函数可以不使用,留空或不调用均可。
  • lv_indev_drv_init(&indev_drv); 初始化管理输入设备的结构体。
  • indev_drv.type = LV_INDEV_TYPE_BUTTON; 指定我们使用的输入设备类型。
  • indev_drv.read_cb = button_read; 指定用于读取按键状态的函数。
  • indev_button = lv_indev_drv_register(&indev_drv); 将实体按键注册到 lvgl 中。
  • 将实体按键映射到软件按键所在的屏幕中心坐标,并将坐标指定给 lvgl,注意中心坐标需要我们根据我们要控制的软件按键坐标在这里自行计算好,并提供给 lvgl,我们计算的坐标必须位于软件按键的中心,不然会发现无法控制,软件按键不会随硬件按键按下而跟着按下)具体如下代码块。
static const lv_point_t btn_points[2] = {
    {10, 10},   /*Button 0 -> x:10; y:10*/
    {40, 100},  /*Button 1 -> x:40; y:100*/
};
lv_indev_set_button_points(indev_button, btn_points);

2.2 修改按键状态读取相关函数

/*------------------
 * Button
 * -----------------*/

/*Initialize your buttons*/
static void button_init(void)
{
    /*Your code comes here*/
}

/*Will be called by the library to read the button*/
static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{

    static uint8_t last_btn = 0;

    /*Get the pressed button's ID*/
    int8_t btn_act = button_get_pressed_id();

    if(btn_act >= 0) {
        data->state = LV_INDEV_STATE_PR;
        last_btn = btn_act;
    } else {
        data->state = LV_INDEV_STATE_REL;
    }

    /*Save the last pressed button's ID*/
    data->btn_id = last_btn;
}

/*Get ID  (0, 1, 2 ..) of the pressed button*/
static int8_t button_get_pressed_id(void)
{
    uint8_t i;

    /*Check to buttons see which is being pressed (assume there are 2 buttons)*/
    for(i = 0; i < 2; i++) {
        /*Return the pressed button's ID*/
        if(button_is_pressed(i)) {
            return i;
        }
    }

    /*No button pressed*/
    return -1;
}

/*Test if `id` button is pressed or not*/
static bool button_is_pressed(uint8_t id)
{

    /*Your code comes here*/
// ----------- add by zhbi ------------------
    if (!F1_KEY_STATUS() == 0) {
        return LV_INDEV_STATE_PR;  // 和 LV_INDEV_STATE_PR 对应 
    } else {
        return LV_INDEV_STATE_REL; // 自己添加和 LV_INDEV_STATE_REL 对应
    } 
// ------------------------------------------
    return false;
}

注意这里主要编写完善 static bool button_is_pressed(uint8_t id) 这个判断物理按键是否被按下的函数,这个函数可以通过 id 来区分每一个物理按键,也就是说可以将所有物理按键的读取都放置在这里实现,实现之后 lvgl 可以通过 id 进行逐个读取。
这里需要实现 的就是获取硬件 IO 的电平,并将电平状态对应为按键的按下释放

2.3 创建一个被控按键

lv_obj_t * container = lv_obj_create(lv_scr_act());
lv_obj_set_size(container, 320, 240);
lv_obj_center(container);

lv_obj_t * button = lv_btn_create(container);
lv_obj_set_size(button, 20, 20);
lv_obj_set_pos(button, 0, 0);
lv_obj_add_event_cb(button, btn_event_cb_1, LV_EVENT_ALL, NULL);

这样独立的 Button 物理按键就可以控制 lvgl 的软件按键了,lvgl 的软件按键会随着物理按键的按下而按下,并呈现相应的动画显示效果。

3. lvgl 接入 Keypad 键盘

前面已经说到 Keypad 属于矩阵键盘,它与 button 独立按键的区别是可以通过返回不同的键值来区分控制的软件按键(换句话说就是通过不同的键值(事件)来控制不同的软件按键,button 按键只有两个键值(事件)就是 PressedReleased),而不需要像 button 独立按键那样给每个每个物理按键分配控制软件按键在屏幕上显示的中心坐标来区分控制。

3.1 修改输入设备初始化函数

因为这里需要对接的是 keypad(矩阵键盘),所以我们将 lv_port_indev.c 模板文件中
void lv_port_indev_init() 初始化函数与 keypad 无相关的内容(比如触摸屏,鼠标,编码器等)先注释(或使用条件编译进行隔离编译),留下需要的 keypad 部分,如下图所示。
lvgl 实体按键,LVGL8.X,stm32,lvgl8.0,lvgl按键驱动,lvgl
从图中可以看出 keypad 的初始化与前面讲解的 button 按键的初始化的步骤是相同的,图中指定的读取回调函数 keypad_read 是矩阵键盘键值读取函数,这个函数也是接下来需要进行完善的地方,其他的与 button 均类似这里不再详细说明。

3.2 修改键盘键值读取相关函数

/*------------------
 * Keypad
 * -----------------*/

/*Initialize your keypad*/
static void keypad_init(void)
{
    /*Your code comes here*/
}

/*Will be called by the library to read the mouse*/
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    static uint32_t last_key = 0;

    /*Get the current x and y coordinates*/
    mouse_get_xy(&data->point.x, &data->point.y);

    /*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_NEXT;
            break;
        case 2:
            act_key = LV_KEY_PREV;
            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 the currently being pressed key.  0 if no key is pressed*/
static uint32_t keypad_get_key(void)
{
    /*Your code comes here*/

// ---------------------- add by zhbi -------------------
    // 这是我添加获取按键值相关的操作
    if (!F1_KEY_STATUS() == 0) {
        return LV_KEY_PREV;   //和 LV_KEY_NEXT 对应 
    } else if (F2_KEY_STATUS() == 0) {
        return LV_KEY_LEFT;   //自己添加和 LV_KEY_HOME 对应
    } else if (F3_KEY_STATUS() == 0) {
        return LV_KEY_ENTER;   //和 LV_KEY_ENTER 对应 
    } else if (F4_KEY_STATUS() == 0) {
        return LV_KEY_RIGHT;   //和 LV_KEY_ENTER 对应 
    }
// ------------------------------------------------------

    return 0;
}

注意这里主要编写完善 static uint32_t keypad_get_key(void) 这个判断某个物理按键是否被按下的函数,这个函数可以通过读取不同的硬件 IO 来区分每一个物理按键,**这里需要实现的就是获取硬件 IO 的电平,并将电平状态对应为某个按键键值(事件)并将事件返回给 lvgl

3.3 创建被控按键

extern lv_indev_t * indev_keypad;

lv_group_t * group = lv_group_create();
lv_indev_set_group(indev_keypad, group);

lv_obj_t * container = lv_obj_create(lv_scr_act());
lv_obj_set_size(container, 320, 240);
lv_obj_center(container);

lv_obj_t * button = lv_btn_create(container);
lv_obj_set_size(button, 60, 35);
// lv_obj_center(button);
lv_obj_set_pos(button, 50, 125);
lv_obj_add_event_cb(button, btn_event_cb_1, LV_EVENT_ALL, NULL);

lv_group_add_obj(group, button);

这里需要使用 lv_group_create() 函数创建一个控件(或者叫做对象)组(group),这是 keypad 矩阵键盘与 button 按键不同的地方,下面详细说明为什么需要创建组。
我们可以试着想象这样的一个场景,当我们的屏幕上存在较多的显示组件需要控制但是具备的物理按键较少时,这时我们就无法使用按键来控制所有的控件修改控件的内容,这时候我们就可以创建一个控件组,并将需要被控制的控件都添加到这个控件组中,lvgl 会在这个控件组中进行控件轮流焦点转换来实现选中不同的控件,这时我们就可以专门使用一个按键进行组中控件的焦点轮流转换,其他按键则用于对控件内容的修改等操作。

3.4 group 的概念

通过上述的对接我们知道 相比buttonkeypad 比较特殊,光移植完还不行,需要使用的话,还需要 indev group

需要使用按键控制一组对象,需要将要使用键盘或编码器控制的对象添加到组中。在每一组中都有一个被聚焦的对象接收按下的按键产生的事件或编码器产生的动作。例如,如果一个文本区域是集中的,您按键盘上的某个字母,键将被发送并插入到文本区域。类似地,如果一个滑块被聚焦,并且你按下向左或向右的箭头,滑块的值将会改变。这些操作的前提是需要将输入设备与组关联起来。一个输入设备只能将密钥发送给一个组,但是一个组也可以接收来自多个输入设备的数据。要创建组,请使用 lv_group_t * g = lv_group_create(); 创建好组之后向组添加对象,添加对象使用 lv_group_add_obj(g, obj)。使用 lv_indev_set_group(indev, group) 将组与输入设备关联,其中 indevlv_indev_drv_register() 的返回值。

group 相关有一些预定义的键有特殊的含义,如下:

LV_KEY_NEXT 下一个对象
LV_KEY_PREV 关注前一个对象
LV_KEY_ENTER 触发LV_EVENT_PRESSED/CLICKED/LONG_PRESSED等事件
LV_KEY_UP 增加价值或向上移动
LV_KEY_DOWN 降低价值或向下移动
LV_KEY_RIGHT 增加价值或向右移动
LV_KEY_LEFT 减少数值或向左移动
LV_KEY_ESC 关闭或退出(例如关闭下拉列表)
LV_KEY_DEL 删除(例如文本区域右边的一个字符)
LV_KEY_BACKSPACE 删除左边的字符(例如在文本区域)
LV_KEY_HOME 转到开始/顶部(例如在文本区域)
LV_KEY_END 转到最后(例如在文本区域)
最重要的特殊键是 LV_KEY_NEXT/PREVLV_KEY_ENTERLV_KEY_UP/DOWN/LEFT/RIGHT
read_cb 函数中,您应该将一些键转换为这些特殊的键,以便在组中导航并与所选对象交互。只使用LV_KEY_LEFT/RIGHT 就足够了,因为大多数对象都可以用它们完全控制。对于编码器,您应该只使用LV_KEY_LEFT,LV_KEY_RIGHTLV_KEY_ENTER文章来源地址https://www.toymoban.com/news/detail-679173.html

到了这里,关于lvgl8.x 对接实体按键驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 国民技术N32G45X移植LVGL8.3+ILI9488

    使用的是自制的一块控制板,主控选用的是国民技术的N32G452VEL7芯片,屏幕大小为3.5寸,驱动型号为ILI9488。 从GitHub中获取LVGL码源: GitHub - lvgl/lvgl at release/v8.3 按照下边图示(步骤1-5)选择V8.3版本并进行下载 打开下载好的LVGL-V8.3文件夹,移植LVGL主要就是操作下边这四份文件(/文

    2024年01月16日
    浏览(45)
  • LVGL8.1版本笔记

    之前学过LVGL6,现在版本更新到LVGL8了,学习下新版本,本文主要是记录一些LVGL8的新特性,区别和lvgl6的不同之处 。 lv_task_handler()的作用: 链接: lv_task_handler()是什么,lvgl到底在while(1)中做了什么 总结:lv_task_handler()中,调用lv_indev_read_task()来处理输入信息,当没有输入时,whi

    2024年01月16日
    浏览(42)
  • LVGL8.2学习笔记

    笔记主要记录LVGL控件基本的编程使用和相关的程序,并且在程序中对使用到的API函数进行简要注解(有些是个人的理解),以便后续根据实际项目所需直接套用对应的控件代码修改使用;本文主要参考的是正点原子的LVGL相关教程。 LVGL控件的基础知识 (1) C语言编写的LVGL以结

    2024年02月16日
    浏览(43)
  • linux(全志F1C100S/F1C200S)系列02:移植LCD st7789驱动,LVGL8.3移植

    st7789V中指定了rst与dc引脚,pio 4 3 对应PE3,pio 4 5对应PE5; 详细配置方式见链接:全志 :gpio使用 需要根据自身硬件配置。 Tips:更改 spi-max-frequency = 32000000 - spi-max-frequency = 100000000; 和 fps = 30; 改为 fps = 60; 感谢楼下老哥提示。 rotate = 90;根据屏幕方向更改。 只需要更改下面的三个地

    2024年01月18日
    浏览(61)
  • idf lvgl8显示触摸移植,st7789v+cst816

    用到的所有文件链接 我整理的lvgl文件:https://gitee.com/BHJ2022/lvgl.git gsm项目地址:https://gitee.com/gsm-wheather-project 1)将gsm中的屏幕及触摸驱动(touch_screen文件夹)直接复制到lvgl_disp_indev的component文件中 2)修改touch_screen的cmakelist如图 3)将gsm中的main中的include直接复制到lvgl_disp_

    2024年02月07日
    浏览(54)
  • STM32移植LVGL+旋转编码器接口对接

    写在前面:本菜鸟结合了许多大佬的文章,成功实现了基于LVGL的GUI设计,小开心~浅浅记录一下!~ 本文以单片机STM32F103VET6为核心,利用ST7796芯片驱动分辨率为480*320的LCD液晶屏模块,移植LVGL,对接显示接口,对接外部接口——旋转编码器,完成以上两步,就可以实现LVGL的显

    2024年02月10日
    浏览(45)
  • STM32 RGB屏幕驱动+LVGL移植 从底层到应用小项目

    项目使用正点原子STM32F767阿波罗开发板+IPS TFT-LCD屏幕(非正点原子屏幕)进行开发,应用层移植轻量级GUI库LVGL实现列表按键点击,切换,显示当前内部工作电压功能。重点在于对于RGB屏幕驱动普适性的学习和LVGL开发的理解。希望我实习期间的项目学习过程能对大家有所帮助

    2024年02月15日
    浏览(34)
  • 07_瑞萨GUI(LVGL)移植实战教程之LVGL对接EC11旋转编码器驱动

    本系列教程配套出有视频教程,观看地址:https://www.bilibili.com/video/BV1gV4y1e7Sg 本次实验我们向LVGL库中对接EC11旋转编码器驱动,让我们能通过EC11旋转编码器操作UI。 上次实验得出的工程我们可以通过复制在原有的基础上得到一个新的工程。 如果你不清楚复制工程的步骤,请参

    2024年02月09日
    浏览(39)
  • [esp32 + LVGL]物理按键控制屏幕上开关和LED闪烁

    IO0 对应按键 控制 IO2LED闪烁,同时当LED亮的时候开关闭合,当LED灭的时候LED闪烁。 为什么这么做,因为手里没有触摸屏。 首先我们要明白开关闭合的原理,对于触摸屏来说,当你触摸开关的时候会触发点击事件,同时给开关控件添加点击事件。 添加点击事件,也就是开关闭

    2024年02月13日
    浏览(41)
  • 【STM32 LVGL基础教程】初识LVGL

    嵌入式系统中的图形用户界面(GUI)已经成为现代设备不可或缺的一部分。STM32系列微控制器广泛用于各种嵌入式应用中,而LittlevGL(LVGL)是一个强大的开源库,用于在STM32上创建出色的GUI。本文将深入探讨LVGL的基础知识,带您了解这个引人注目的库。 LVGL,全称为Littlev Gr

    2024年02月04日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包