打印
[技术问答]

LVGL多个对象公用一个回调函数的算法

[复制链接]
2478|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jimmhu|  楼主 | 2025-1-25 23:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
LVGL多个对象公用一个回调函数的算法

如果我们使用传统的LVGL对象公用一个回调函数,可能使用以下源码操作,为了俭省代码的篇幅如以下源码所示,所以利用链表的形式查找那个对象按下。



void event_cb(lv_event_t *event)

{

    lv_event_code_t code = lv_event_get_code(event);

    lv_obj_t * obj = lv_event_get_target(event);



    if (code == LV_EVENT_CLICKED)

    {

        if (obj == obj1)

        {

            /* 进行对象1的代码 */



        }



        else if (obj == obj2)

        {

            /* 执行对象2的代码 */



        }

        else if ()

        {

            /* 多个对象 */

        }

        ........



    }

}
    如果按照上述的写法,造成获取对象是否按下的代码篇幅很大等问题,我们怎么样去简化这个代码呢。

    既然我们把多个对象公共一个回调函数,那么我们可以先把共用的lvgl对象控制块放到一个数组里面,如以下源码所示:

lv_obj_t *lv_obj_app[20];/* 这里可以设置多个对象 */


    然后呢?小编主要参考FreeRTOS的内核寻找最高优先级的算法,首先先定义一个32位的变量,如以下源码所示:

/* obj就绪表-->32位的 */

unsigned int  obj_readly_list;
    注意:这里就是一个无符号的整形,所以一开始就是32bit(000000.....00)

    然后我们在回调函数中遍历按下的对象

void event_cb(lv_event_t *event)

{

    lv_event_code_t code = lv_event_get_code(event);

    lv_obj_t * obj = lv_event_get_target(event);



    if (code == LV_EVENT_CLICKED)

    {

        for (int i = 0;i < app_mun;i ++)

        {

            if (obj == lv_obj_app[i])

            {

                /* obj就绪表位置1 */

                obj_readly_list |= 1 << i;

            }

        }

        /* 计算前导指令 */

        lv_trigger_bit = (31UL -  ( unsigned char )

__clz( ( obj_readly_list ) ) );

        /* 该位清零就绪表 */

        obj_readly_list &= ~(1 << lv_trigger_bit);

         /* 根据该位做相应的函数 */

        switch(lv_trigger_bit)

        {

            case 0:

              /* 对象0处理的任务 */

            break;

            case 1:

              /* 对象1处理的任务 */

              break;

            case 2:

              /* 对象2处理的任务 */

              break;

            case 3:

              /* 对象3处理的任务 */

              break;

            case 4:

              /* 对象4处理的任务 */

              break;

            default:

              break;

        }

    }



}
代码分析

上述源码可知:for语句主要就是或者按下的对象,例如我们有5个LVGL对象,保存在一个数组lv_obj_app里面

所以lv_obj_app[0]等于obj0、

lv_obj_app [1]等于obj1、

lv_obj_app [2]等于obj2、

lv_obj_app [3]等于obj3、

lv_obj_app [4]等于obj4。
    当按下obj0时,然后调用以下函数对象就绪表obj_readly_list相应位置1,如以下源码所示:

obj_readly_list |= 1 << i; /* 也就是说:obj_readly_list = (0...001); */
    然后调用以下函数获取就绪链表的就绪位那个为1,如以下源码所示:

/* 计算前导指令 */

lv_trigger_bit = (31UL -  ( unsigned char )

                     __clz( ( obj_readly_list ) ) );
    __clz这个函数就是计算前导0的个数,什么意思呢,例如__clz(00001)= 4,因为前面是4个0,所以等于4,

    刚刚说obj0按下所以obj_readly_list =(0...001)所以__clz(obj_readly_list)就等于31,所以lv_trigger_bit= 31-31等于0。

    最后使用switch来判定对象执行的代码。

使用特权

评论回复
沙发
hhdhy| | 2025-3-7 14:07 | 只看该作者
在LVGL中,为了优化资源使用和代码的可维护性,经常需要多个对象共用一个回调函数。这种方法可以显著减少内存占用并提高代码的可读性。

使用特权

评论回复
板凳
ewyu| | 2025-3-7 15:16 | 只看该作者
编写一个通用的回调函数,该函数根据传递给它的参数来区分是哪个对象触发了事件。

使用特权

评论回复
地板
gongqijuns| | 2025-3-7 16:24 | 只看该作者
传递用户数据,在创建LVGL对象时,使用lv_obj_add_event_cb函数为每个对象添加回调函数,并通过lv_event_data_t结构体的user_data字段传递一个指向特定数据的指针。这个数据可以是任何有助于回调函数识别触发事件对象的信息。

使用特权

评论回复
5
hight1light| | 2025-3-7 17:45 | 只看该作者
在回调函数中区分对象,在回调函数中,使用lv_event_get_target获取触发事件的对象,并使用lv_event_get_data获取用户数据。根据这些信息,回调函数可以执行不同的操作

使用特权

评论回复
6
yuliangren| | 2025-3-7 18:55 | 只看该作者
在实际项目中,记得释放分配的内存(例如,使用lv_mem_free释放用户数据)。

使用特权

评论回复
7
星星点点didi| | 2025-3-7 20:13 | 只看该作者
共用的话好像有利于代码的维护

使用特权

评论回复
8
pe66ak| | 2025-3-8 09:04 | 只看该作者
一般来说就是定义好回调函数和传递函数就可以了

使用特权

评论回复
9
eleg34ance| | 2025-3-8 10:28 | 只看该作者
这种话说lvgl的话是否有相应的例程呢?

使用特权

评论回复
10
gra22ce| | 2025-3-8 13:01 | 只看该作者
虽然说共用方便一些,但是如果不好写的话其实分开弄也可以的

使用特权

评论回复
11
miltk| | 2025-3-8 14:27 | 只看该作者
估计魔改回调函数应该就行,在回调函数里判断哪个数据过来的呗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

3647

帖子

4

粉丝