有什么昵称不存在 2024-03-15 14:51 采纳率: 66.7%
浏览 93
已结题

lvgl多线程处理数据显示

最近在使用linux板子跑lvgl,想先实现简单的串口通信功能,即让串口接收到的数据实时显示到lvgl的文本框里,但是发现在多次显示是屏幕无法清除上一次显示的内容,而且文本框显示串口数据的速度不理想,请问在这种lvgl多线程工作中的文本更新是否有更好的建议?

以下是·我的代码段:

static void *uart_read(void *arg)
{
    char receive_buf[255] = {0};
    int recv_len = 0;
    int fd = *(int *)arg;
    while (1)
    {
        recv_len = read(fd, receive_buf, sizeof(receive_buf) - 1);
        if (recv_len > 0)
        {
            printf("Receive_len=%d\n", recv_len);
            printf("Received: %.*s\n", recv_len, receive_buf);

            pthread_mutex_lock(&mutex);
            lv_textarea_set_text(label_1, "");    //在这里并不能及时清除文本框的内容
            lv_textarea_set_text(label_1, receive_buf);//label_1为接收文本框
            pthread_mutex_unlock(&mutex);
        }

        usleep(5 * 1000);
    }
    pthread_exit(NULL);
}


int main(int argc, char *argv[])
{
    const char *fb_path = "/dev/fb0";
    const char *tp_path = "/dev/input/event0";

    char buf[255];
    int n;

    // 打开串口设备
    fd = open_port("/dev/ttyS3");
    if (fd == -1)
    {

        printf("open err\n");
        exit(1);
    }
    else
    {
        printf("open uart\n");
    }

    lv_init();

    int ret;
    ret = lvgl_init_fb_display(fb_path);
    assert(!ret);

    ret = lvgl_init_tp_input(tp_path);
    // assert(!ret);

    lv_demo();    //lvgl工程

    pthread_t tid1;
    ret = pthread_create(&tid1, NULL, uart_read, &fd);
    while (1)
    {
        pthread_mutex_lock(&mutex);
        lvgl_usleep_once(5 * 1000);  //封装的lv_timer_handler 函数
        pthread_mutex_unlock(&mutex);
    }
    return 0;
}

当前效果:
第一次串口数据:12345678
第二次串口数据:mjkl

img

img

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-15 14:52
    关注

    引自免费微信小程序:皆我百晓生

    在LVGL中,为了实现在多线程环境下实时更新UI组件(如文本框)的内容,并确保显示内容正确无误和流畅,你需要对当前的代码进行优化。这里有几个建议:

    1. 屏幕刷新问题:由于LVGL的UI更新是基于事件循环驱动的,在主线程中你应该调用lv_task_handler()来处理所有UI更新任务。将串口接收线程与UI更新线程解耦,避免直接在接收线程中更新UI。

      修改main()函数中的无限循环,使其只负责调用lv_task_handler()以处理UI更新:

      while (1) {
          pthread_mutex_lock(&mutex);
          lvgl_usleep_once(5 * 1000);  // 这里改为调用lv_task_handler()
          lv_task_handler();  // 添加此行
          pthread_mutex_unlock(&mutex);
      }
      
    2. 串口数据处理:在串口读取线程中,将接收到的数据暂存到一个全局缓冲区或队列中,而不是直接更新UI。创建一个新的定时器任务,在LVGL的任务循环中处理这个缓冲区或队列中的数据并更新文本框。

      创建一个全局缓冲区和队列结构体:

      static char uart_recv_buf[255];
      static struct queue_t {
          char data[255];
          size_t len;
      } uart_queue = {0};
      

      然后修改uart_read()函数,将数据存入队列:

      static void *uart_read(void *arg)
      {
          int recv_len;
          while (1)
          {
              recv_len = read(fd, uart_recv_buf, sizeof(uart_recv_buf) - 1);
              if (recv_len > 0)
              {
                  printf("Receive_len=%d\n", recv_len);
                  printf("Received: %.*s\n", recv_len, uart_recv_buf);
      
                  // 将数据添加到队列
                  pthread_mutex_lock(&mutex);
                  memcpy(uart_queue.data, uart_recv_buf, recv_len);
                  uart_queue.len = recv_len;
                  pthread_mutex_unlock(&mutex);
              }
      
              usleep(5 * 1000);
          }
          pthread_exit(NULL);
      }
      
    3. 定时器回调处理数据:创建一个LVGL定时器,定期检查队列并更新文本框内容。

      static void timer_callback(lv_timer_t *timer)
      {
          pthread_mutex_lock(&mutex);
      
          if (uart_queue.len > 0) {
              lv_textarea_set_text(label_1, "");    // 清除文本框内容
              lv_textarea_add_text(label_1, uart_queue.data); // 添加新数据
              uart_queue.len = 0;  // 清空队列
          }
      
          pthread_mutex_unlock(&mutex);
      }
      
      // 在main()函数初始化部分添加定时器
      lv_timer_t *my_timer = lv_timer_create(timer_callback, 100 /* 更新频率 */, NULL);
      lv_timer_start(my_timer);
      

    这样,你就可以在一个安全、高效且不会阻塞UI更新的方式下,实现串口数据显示到LVGL文本框的功能了。记得调整定时器的触发间隔以获得最佳性能和实时性。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 3月26日
  • 已采纳回答 3月18日
  • 创建了问题 3月15日

悬赏问题

  • ¥15 模电中二极管,三极管和电容的应用
  • ¥15 关于模型导入UNITY的.FBX: Check external application preferences.警告。
  • ¥15 气象网格数据与卫星轨道数据如何匹配
  • ¥100 java ee ssm项目 悬赏,感兴趣直接联系我
  • ¥15 微软账户问题不小心注销了好像
  • ¥15 x264库中预测模式字IPM、运动向量差MVD、量化后的DCT系数的位置
  • ¥15 curl 命令调用正常,程序调用报 java.net.ConnectException: connection refused
  • ¥20 关于web前端如何播放二次加密m3u8视频的问题
  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络