OpenEdv-开源电子网

 找回密码
 立即注册
查看: 2639|回复: 0

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

[复制链接]

1057

主题

1068

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4391
金钱
4391
注册时间
2019-5-8
在线时间
1195 小时
发表于 2021-9-11 18:22:45 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2021-11-1 10:35 编辑

以下文章摘自微信公众号——开源电子网《LVGL多个对象公用一个回调函数的算法》
更多技术文章,请扫下方二维码关注

开源电子网,扫码2222222.png





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



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

  1. void event_cb(lv_event_t *event)

  2. {

  3.     lv_event_code_t code = lv_event_get_code(event);

  4.     lv_obj_t * obj = lv_event_get_target(event);



  5.     if (code == LV_EVENT_CLICKED)

  6.     {

  7.         if (obj == obj1)

  8.         {

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



  10.         }



  11.         else if (obj == obj2)

  12.         {

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



  14.         }

  15.         else if ()

  16.         {

  17.             /* 多个对象 */

  18.         }

  19.         ........



  20.     }

  21. }
复制代码

如果按照上述的写法,造成获取对象是否按下的代码篇幅很大等问题,我们怎么样去简化这个代码呢。
既然我们把多个对象公共一个回调函数,那么我们可以先把共用的lvgl对象控制块放到一个数组里面,如以下源码所示:

  1. lv_obj_t *lv_obj_app[20];/* 这里可以设置多个对象 */
复制代码

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

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

  2. unsigned int  obj_readly_list;
复制代码

注意:这里就是一个无符号的整形,所以一开始就是32bit(000000.....00)
然后我们在回调函数中遍历按下的对象



  1. <font size="4">void event_cb(lv_event_t *event)

  2. {

  3.     lv_event_code_t code = lv_event_get_code(event);

  4.     lv_obj_t * obj = lv_event_get_target(event);



  5.     if (code == LV_EVENT_CLICKED)

  6.     {

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

  8.         {

  9.             if (obj == lv_obj_app</font><i><font size="4">)

  10.             {

  11.                 /* obj就绪表位置1 */

  12.                 obj_readly_list |= 1 << i;

  13.             }

  14.         }

  15.         /* 计算前导指令 */

  16.         lv_trigger_bit = (31UL -  ( unsigned char )

  17. __clz( ( obj_readly_list ) ) );

  18.         /* 该位清零就绪表 */

  19.         obj_readly_list &= ~(1 << lv_trigger_bit);

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

  21.         switch(lv_trigger_bit)                  

  22.         {

  23.             case 0:

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

  25.             break;

  26.             case 1:

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

  28.               break;

  29.             case 2:

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

  31.               break;

  32.             case 3:

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

  34.               break;

  35.             case 4:

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

  37.               break;

  38.             default:

  39.               break;

  40.         }

  41.     }



  42. }</font></i>
复制代码

代码分析
上述源码可知:for语句主要就是或者按下的对象,例如我们有5个LVGL对象,保存在一个数组lv_obj_app里面
  1. <i><font size="4">
  2.     所以lv_obj_app[0]等于obj0、

  3.     lv_obj_app [1]等于obj1、

  4.     lv_obj_app [2]等于obj2、

  5.     lv_obj_app [3]等于obj3、

  6. </font></i><div><i><font size="4">    lv_obj_app [4]等于obj4。</font></i></div>
复制代码



当按下obj0时,然后调用以下函数对象就绪表obj_readly_list相应位置1,如以下源码所示:


  1. obj_readly_list |= 1 << i; /* 也就是说:obj_readly_list = (0...001); */

复制代码


然后调用以下函数获取就绪链表的就绪位那个为1,如以下源码所示:

   
  1. /* 计算前导指令 */

  2.     lv_trigger_bit = (31UL -  ( unsigned char )

  3.                          __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来判定对象执行的代码。
是不是很简单的操作,这个灵感来着FreeRTOS操作系统的查找就绪链表的最高优先级的算法。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-24 04:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表