Navigation

    全志在线开发者论坛

    • Register
    • Login
    • Search
    • Categories
    • Tags
    • 在线文档
    • 社区主页

    mango-MQ-R在移植好的lvgl添加物理按键

    MR Series
    1
    1
    1023
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      bigfly LV 5 last edited by

      续上篇:mango-MQ-R基于Melis移植lvgl

      没有搞定D1s在Melis下的I2c驱动(gt911触摸屏)。先测试物理按键。

      1.lvgl注册keypad驱动

      ##1.1 在melis的ADC按键中发送消息
      先做好ADC按键的驱动,直接在驱动中发送消息。

      如何在rt-thread中使用消息队列发送消息,请参考官方资料: RT-Thread API参考手册-消息队列

      1.1.1 创建消息队列,并初始化

      相关代码在 D1s-Melis/ekernel/drivers/drv/source/input/keyboard/sunxi_keyboard.c 中。完整内容点击链接 sunxi_keyboard.c。

      /* 消息队列控制块 */
       struct rt_messagequeue mq;
      /* 消息队列中用到的放置消息的内存池 */
      static rt_uint8_t msg_pool[2048];
      int sunxi_keyboard_init(void)
      {
      ......
          rt_err_t result;
          /* 初始化消息队列 */
          result = rt_mq_init(&mq,
                              "mqt",
                              &msg_pool[0],               /* 内存池指向msg_pool */
                              1,                          /* 每个消息的大小是 1 字节 */
                              sizeof(msg_pool),           /* 内存池的大小是msg_pool的大小 */
                              RT_IPC_FLAG_FIFO);          /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
          if (result != RT_EOK)
          {
              rt_kprintf("init message queue failed.\n");
              return -1;
          }
          return 0;
      }
      

      1.1.2 扫描按键时,发送按下和松开消息

      这部分代码也在 sunxi_keyboard.c 中。

      int keyboard_irq_callback(uint32_t data_type, uint32_t data)
      {
          if (data_type == GPADC_UP && key_flag == 1)
          {
      ......
                                  /* 发送按键松开消息到消息队列中 */
                                  key_data->compare_later = 0xf6;
                                  result = rt_mq_send(&mq, &(key_data->compare_later), 1);
                                  if (result != RT_EOK)
                                  {
                                      rt_kprintf("rt_mq_send ERR\n");
                                  }
          }
          .......
                                  __log("key: %d",key_data->compare_before);
                                  /* 发送按键按下消息到消息队列中 */
                                  result = rt_mq_send(&mq, &(key_data->compare_before), 1);
                                  if (result != RT_EOK)
                                  {
                                      rt_kprintf("rt_mq_send ERR\n");
                                  } 
          return 0;
      }
      

      1.2 编写读取按键的回调函数

      这里只是通过消息队列读取按键按下和松开的消息。

      收到按键按下的消息值为0,1,2,3,4;
      收到按键松开的消息值为0xF6.

      extern   struct rt_messagequeue mq;
      uint8_t   msgbyte;
      static void melis_keypad_driver_read_cb(lv_indev_drv_t* indev_drv,    lv_indev_data_t* data)
      {
          /* 从消息队列中接收消息 */
          if (rt_mq_recv(&mq, (void *)&msgbyte, sizeof(msgbyte), RT_WAITING_NO) == RT_EOK)
          {
              rt_kprintf("read_cb: recv msg:%d\n", msgbyte);
              data->state = LV_INDEV_STATE_PR;
              switch (msgbyte)
              {
              case 0:
                  data->key = LV_KEY_PREV;            break;
              case 1:
                  data->key = LV_KEY_NEXT;            break;
              case 2:
                  data->key = LV_KEY_ENTER;            break;
              case 3:
                  data->key = LV_KEY_ENTER;            break;
              case 4:
                  data->key = LV_KEY_ESC;            break;
              case 0xf6:
                data->state = LV_INDEV_STATE_REL;	break;
              default:
                  break;
              }
          }
      }
      

      1.3 lvgl按键驱动注册

      完成前面的准备工作后,就可以在 lv_main()中注册按键驱动,完成lvgl物理按键的初始化。

      直接拷贝韦东山老师在windows下键盘的驱动,00_lv_100ask_sim_codeblocks_win/lv_drivers/win32drv/win32drv.c 完整代码点击链接:

      static lv_indev_drv_t keypad_driver;
          lv_indev_drv_init(&keypad_driver);
          keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
          keypad_driver.read_cb = lv_win32_keypad_driver_read_callback;
          lv_win32_keypad_device_object = lv_indev_drv_register(&keypad_driver);
      

      把上面的代码稍作改动。

      lv_win32_keypad_driver_read_callback --> melis_keypad_driver_read_cb
      lv_win32_keypad_device_object --> g_keypad_device_object 【 说明:这个变量其他文件需要用到】
      

      于是,改动后的代码如下(完整代码点击链接 lv_main.c):

      #define   LV_USE_GPADC    1
      lv_indev_t* g_keypad_device_object ;
      static lv_disp_t * hal_init(void  )
      {
      ......
      #if   LV_USE_GPADC    
          static lv_indev_drv_t keypad_driver;
          lv_indev_drv_init(&keypad_driver);
          keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
          keypad_driver.read_cb = melis_keypad_driver_read_cb;
          g_keypad_device_object = lv_indev_drv_register(&keypad_driver);
      #endif
      	lv_disp_t * disp = NULL;
        return disp;
      }
      

      2.在gui中测试物理按键效果

      在gui中应用物理按键(groups)需要3个步骤:

      1.要创建一个 组(Groups) : lv_group_t * g = lv_group_create();
      2.然后将一个对象添加到 组(Groups) 中: lv_group_add_obj(g, obj); 也可以指定默认组:lv_group_set_default(g);
      3.最后要将组(Groups)与输入设备相关联: lv_indev_set_group(g_keypad_device_object , g);

      物理按键中有3个必备的按键消息,这3个消息就可以实现焦点切换和触发焦点对象:

      消息名称 含义
      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_example_btn_1.c。

      extern lv_indev_t* g_keypad_device_object ;
      static void event_handler(lv_event_t * e)
      {
          lv_event_code_t code = lv_event_get_code(e);
      
          if(code == LV_EVENT_CLICKED) {
              LV_LOG_USER("Clicked");
          }
          else if(code == LV_EVENT_VALUE_CHANGED) {
              LV_LOG_USER("Toggled");
          }
      }
      
      void lv_example_btn_1(void)
      {
          lv_obj_t * label;
      
          // 创建一个组,稍后将需要使用键盘或编码器或按钮控制的部件(对象)添加进去,并且将输入设备和组关联
          // 如果将这个组设置为默认组,那么对于那些在创建时会添加到默认组的部件(对象)就可以省略 lv_group_add_obj()
          lv_group_t * g = lv_group_create();
      
          // 将上面创建的组设置为默认组
          // 如果稍后创建的部件(对象),使用默认组那必须要在其创建之前设置好默认组,否则不生效
          lv_group_set_default(g);
      
          lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
          lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);
          lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);
      
          label = lv_label_create(btn1);
          lv_label_set_text(label, "Button");
          lv_obj_center(label);
      
          lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
          lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL);
          lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
          lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
          lv_obj_set_height(btn2, LV_SIZE_CONTENT);
      
          label = lv_label_create(btn2);
          lv_label_set_text(label, "Toggle");
          lv_obj_center(label);
      
          lv_indev_set_group(g_keypad_device_object, g);
      }
      

      原文链接:https://blog.csdn.net/hwd00001/article/details/130106367

      1 Reply Last reply Reply Quote Share 0
      • 1 / 1
      • First post
        Last post

      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策