打印
[技术问答]

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

[复制链接]
177|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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来判定对象执行的代码。

使用特权

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

本版积分规则

18

主题

3588

帖子

4

粉丝