嵌入式图形界面库lvgl使用详解

  • Post author:
  • Post category:其他

前言

本文相当一个快速入门的lvgl学习教程,主要记录了lvgl在vscode开发环境的配置,以及相关的环境配置,最后通过实例熟悉lvgl的使用。
下面主要参考了lvgl中文文档,还有一个优秀博主的系列博文

(一)lvgl ubuntu环境vscode模拟器安装配置

一开始接触lvgl时,lvgl版本已经更新到了8.0了,但网上的教程大多数时7.11的,在配置vscode lvgl模拟器开发环境lv_sim_vscode_sdl的时候遇到了些麻烦。

1.首先,github在国内访问速度极慢,直接git clone几乎失效,
2.lv_examples是对应lvgl 7.11的,当前lvgl 8.0对应的lv_examples已经改名为了lv_demos,git clone下来的也是lv_demos.
3.lv_drivers,lvgl需要自己现在配置

我把配置好的lv_sim_vscode_sdl的项目配置好后,直接发布在到了gitee上。
下面是安装过程。

//安装sdl
sudo apt-get update && sudo apt-get install -y build-essential libsdl2-dev

//git clone 项目
git clone https://gitee.com/lingcb/lv_sim_vscode_sdl-7.11.0.git

当环境安装了vscode时,双击文件simulator.code-workspace,打开项目。若打不开,直接使用vscode打开文件夹。
在这里插入图片描述

(二)lvgl lv_conf.h环境配置

lv_conf.h文件里可以设置屏幕的大小
下面的具体变量

#define LV_HOR_RES_MAX          (240)
#define LV_VER_RES_MAX          (320)

需要注意的点是,若项目编译运行了,生成了build文件夹,需要删除 build文件夹,再重新按F5重新运行,在lv_conf.h上的配置才生效。

之后的运行几个经典的例子,可以参考这篇博文后面部分。

(三)lvgl 控件使用的几个例子

这里给几个使用的例子。

(1)bar.h

创建一个文件“bar.h”,在上面的项目里的“main.c”,导入下面的bar.h代码。根据图片的位置上添加直接运行,便可。后续的几个控件的运行,基本差不多。

//参考:http://lvgl.100ask.org/7.11/documentation/04_widgets/03_bar.html
//导入lvgl载入h文件
#include "../lvgl/lvgl.h"
//定义控件,及相关事件
static void bar()
{
    lv_obj_t * bar1 = lv_bar_create(lv_scr_act(), NULL);
    lv_obj_set_size(bar1, 200, 20);
    lv_obj_align(bar1, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_bar_set_anim_time(bar1, 20000);
    lv_bar_set_value(bar1, 100, LV_ANIM_ON);
}

在这里插入图片描述

(2)button.h

//参考:http://lvgl.100ask.org/7.11/documentation/04_widgets/04_btn.html
//导入lvgl载入h文件
#include <stdio.h>
#include "../lvgl/lvgl.h"

//定义控件,及相关事件
static void event_handler(lv_obj_t * obj, lv_event_t event)
     {
             if(event == LV_EVENT_CLICKED) {
                     printf("Clicked\n");
             }
            else if(event == LV_EVENT_VALUE_CHANGED) {
                    printf("Toggled\n");
            }
    }

static void button()
{
    lv_obj_t * label;
    lv_obj_t * btn1 = lv_btn_create(lv_scr_act(), NULL);
     lv_obj_set_event_cb(btn1, event_handler);
    lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, -40);
            
    label = lv_label_create(btn1, NULL);
    lv_label_set_text(label, "Button");

     lv_obj_t * btn2 = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_event_cb(btn2, event_handler);
    lv_obj_align(btn2, NULL, LV_ALIGN_CENTER, 0, 40);
    lv_btn_set_checkable(btn2, true);
    lv_btn_toggle(btn2);
    lv_btn_set_fit2(btn2, LV_FIT_NONE, LV_FIT_TIGHT);

    label = lv_label_create(btn2, NULL);
    lv_label_set_text(label, "Toggled");    
}

(3)image.h

//参考:http://lvgl.100ask.org/7.11/documentation/04_widgets/14_img.html
//导入lvgl载入h文件
#include "../lvgl/lvgl.h"

//定义控件,及相关事件
#define SLIDER_WIDTH 20
static void create_sliders(void);
static void slider_event_cb(lv_obj_t * slider, lv_event_t event);
 
static lv_obj_t * red_slider, * green_slider, * blue_slider, * intense_slider;
static lv_obj_t * img1;
LV_IMG_DECLARE(img_cogwheel_argb);

static void slider_event_cb(lv_obj_t * slider, lv_event_t event)
    {
        if(event == LV_EVENT_VALUE_CHANGED) {
                    /* Recolor the image based on the sliders' values */
                    lv_color_t color  = lv_color_make(lv_slider_get_value(red_slider), lv_slider_get_value(green_slider), lv_slider_get_value(blue_slider));
                    lv_opa_t intense = lv_slider_get_value(intense_slider);
                    lv_obj_set_style_local_image_recolor_opa(img1, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, intense);
                    lv_obj_set_style_local_image_recolor(img1, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, color);
            }
    }

    static void create_sliders(void)
    {
            /* Create a set of RGB sliders */
            /* Use the red one as a base for all the settings */
            red_slider = lv_slider_create(lv_scr_act(), NULL);
            lv_slider_set_range(red_slider, 0, 255);
            lv_obj_set_size(red_slider, SLIDER_WIDTH, 200); /* Be sure it's a vertical slider */
            lv_obj_set_style_local_bg_color(red_slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED);
            lv_obj_set_event_cb(red_slider, slider_event_cb);
            /* Copy it for the other three sliders */
            green_slider = lv_slider_create(lv_scr_act(), red_slider);
            lv_obj_set_style_local_bg_color(green_slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_LIME);

            blue_slider = lv_slider_create(lv_scr_act(), red_slider);
            lv_obj_set_style_local_bg_color(blue_slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE);

            intense_slider = lv_slider_create(lv_scr_act(), red_slider);
            lv_obj_set_style_local_bg_color(intense_slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GRAY);
            lv_slider_set_value(intense_slider, 255, LV_ANIM_OFF);

            lv_obj_align(red_slider, NULL, LV_ALIGN_IN_LEFT_MID, 20, 0);
            lv_obj_align(green_slider, red_slider, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
            lv_obj_align(blue_slider, green_slider, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
            lv_obj_align(intense_slider, blue_slider, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
    }

static void image(void){
    create_sliders();
    /* Now create the actual image */
    img1 = lv_img_create(lv_scr_act(), NULL);
    lv_img_set_src(img1, &img_cogwheel_argb);
    lv_obj_align(img1, NULL, LV_ALIGN_IN_RIGHT_MID, -20, 0);
}

(4)label.h

//参考:http://lvgl.100ask.org/7.11/documentation/04_widgets/17_label.html
//导入lvgl载入h文件
#include "../lvgl/lvgl.h"

//定义控件,及相关事件
static void label()
{
    lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK);     /*Break the long lines*/
    lv_label_set_recolor(label1, true);                      /*Enable re-coloring by commands in the text*/
    lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER);       /*Center aligned lines*/
    lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label "
                                                                "and  wrap long text automatically.");
    lv_obj_set_width(label1, 150);
    lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -30);

    lv_obj_t * label2 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL_CIRC);     /*Circular scroll*/
    lv_obj_set_width(label2, 150);
    lv_label_set_text(label2, "It is a circularly scrolling text. ");
    lv_obj_align(label2, NULL, LV_ALIGN_CENTER, 0, 30); 
}

(5)switch.h

//参考:http://lvgl.100ask.org/7.11/documentation/04_widgets/29_switch.html
//导入lvgl载入h文件
#include <stdio.h>
#include "../lvgl/lvgl.h"

//定义控件,及相关事件
static void switch_event_handler(lv_obj_t * obj, lv_event_t event)
     {
             if(event == LV_EVENT_VALUE_CHANGED) {
                     printf("State: %s\n", lv_switch_get_state(obj) ? "On" : "Off");
             }
    }
static void _switch()
{
    lv_obj_t *sw1 = lv_switch_create(lv_scr_act(), NULL);
    lv_obj_align(sw1, NULL, LV_ALIGN_CENTER, 0, -50);
    lv_obj_set_event_cb(sw1, switch_event_handler);
    /*Copy the first switch and turn it ON*/
    lv_obj_t *sw2 = lv_switch_create(lv_scr_act(), sw1);
     lv_switch_on(sw2, LV_ANIM_ON);
    lv_obj_align(sw2, NULL, LV_ALIGN_CENTER, 0, 50);
}

(四)lvgl 任务(task)使用

lvgl task添加后,可以自动定时运行。
使用方法依旧如上。

//参考:https://blog.csdn.net/weixin_41572450/article/details/111546117
//导入lvgl载入h文件
#include "../lvgl/lvgl.h"

//basic variables
uint8_t test_data = 0;
lv_obj_t * label1;

//define label
static void task_label()
{
    label1 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK);     /*Break the long lines*/
    lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER);                /*Center aligned lines*/
    lv_label_set_text(label1, "Hello World!");
    lv_obj_set_width(label1, 150);
    lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -30);
}

//callback function
static void task_cb(lv_task_t* task)
{
    uint8_t *user_data = (uint8_t*)task->user_data;
    (*user_data)++;
    lv_label_set_text_fmt(label1, "Value: %d", *user_data);
}

//creat a task
void task(void)
{
     task_label();
    lv_task_t * t = lv_task_create(task_cb,1000,LV_TASK_PRIO_MID, &test_data);
}

(五)lvgl 图片(使用)

lvgl 可以通过C array导入图片显示,下面是一个使用图片的例子。imgs/backgroud.h lvgl官方提供的在线转换器转换而来,当图片上传,转换的结果格式是.c的,下载来后修改格式为.h就可以直接导入了。需要注意一点:当上传图片后,会出现File name(s)这选项,里面提前命名好,后面的引用会直接用到。

//参考:https://blog.csdn.net/weixin_41572450/article/details/111546117
//导入lvgl载入h文件
#include "../lvgl/lvgl.h"
#include "imgs/backgroud.h"

//basic variables
uint8_t pos_data = 0;
lv_obj_t * pos_label;

//define label
static void posxyz_label()
{
    //setting backgroud
    //LV_IMG_DECLARE(backgroud_map);
    img1 = lv_img_create(lv_scr_act(), NULL);
    lv_img_set_auto_size(img1, true);
    lv_img_set_src(img1, &backgroud);
    lv_obj_align(img1, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0);
    //setting label
    pos_label = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(pos_label, LV_LABEL_LONG_BREAK);     /*Break the long lines*/
    lv_label_set_align(pos_label, LV_LABEL_ALIGN_CENTER);                /*Center aligned lines*/
     // set font size
    static lv_style_t font_style;
	lv_style_init(&font_style);
	lv_style_set_text_font(&font_style, LV_STATE_DEFAULT, &lv_font_montserrat_30);
	lv_obj_add_style(pos_label,LV_LABEL_PART_MAIN, &font_style);
    //setting basic
    lv_label_set_text(pos_label, "\nStart");
    lv_obj_set_width(pos_label, 150);
    lv_obj_align(pos_label, NULL, LV_ALIGN_CENTER, 0, -30);

}

//callback function
static void pos_task_cb(lv_task_t* task)
{
    uint8_t *user_data = (uint8_t*)task->user_data;
    (*user_data)++;
    uint8_t x;
    uint8_t y;
    uint8_t z;

    if (*user_data>=9999){
        *user_data=0;
    }
    
    x =  ((*user_data)%1000)/100;
    y =  ((*user_data)%100)/10;
    z =  ((*user_data)%10);

    lv_label_set_text_fmt(pos_label, "\n%d,%d,%d", x,y,z);
}

//creat a task
void pos_task(void)
{
     posxyz_label();
    lv_task_t * t = lv_task_create(pos_task_cb,100,LV_TASK_PRIO_MID, &pos_data);
}



版权声明:本文为weixin_45259896原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。