项目经验分享:LVGL编程举例

news/2024/10/30 13:31:34/

本文介绍如何在成功移植LVGL的基础之上,编写自己的LVGL GUI程序。

文章目录

  • 1. LVGL组件简介与LVGL仿真
    • 1.1 LVGL组件
    • 1.2 LVGL仿真
  • 2. 代码结构
  • 3. 编程目标
  • 4. 编程前的准备
  • 5. LVGL编程基础
    • 5.1 简单示例代码
    • 5.2 设置组件位置
    • 5.3 图片的显示
    • 5.4 组件的事件响应
    • 5.5 设置定时任务
  • 6. 各个组件编程的实现
    • 6.1 文本标签组件(lv_label)
    • 6.2 开关组件(lv_switch)
    • 6.3 图片按键组件(lv_btn)
    • 6.4 设置定时任务(lv_timer)
    • 6.5 显示其他组件
  • 7. 代码测试
  • 8. 工程源码
  • 参考文档

1. LVGL组件简介与LVGL仿真

1.1 LVGL组件

与绝大多数GUI组件相似,LVGL的GUI组件主要包括Lable(标签)、Button(按键)、Image(图片)、Image Button(图片按钮)、Keyboard(键盘)、Calendar(日历表)、Chart(数据表)等。LVGL组件的官方文档如下:

Welcome to the documentation of LVGL! — LVGL documentation

LVGL编程采用了类似QT的面向对象的编程方法,但是使用的编程语言是C而不是C++,创建LVGL组件对象的方法如下:

lv_obj_t              *my_obj = lv_XXX_create(lv_scr_act());

LVGL中所有的组件对象都是由lv_obj_t来定义的,并通过对应的组件创建函数lv_XXX_create来创建相关的对象。lv_scr_act()表示对组件赋予显示功能。

1.2 LVGL仿真

直接在Linux系统中进行LVGL GUI界面编程不方便,也不利于时刻显示编程结果,这里建议在CodeBlock中使用LVGL模拟仿真器,来实时知晓自己编程的结果,对应的教程如下:

在CodeBlock中实现LVGL模拟仿真

本文先在CodeBlock中进行LVGL的仿真,然后再将源码放在Linux下进行编译与移植,使用的显示屏分辨率为800*480。

2. 代码结构

编程的代码结构如下:

在这里插入图片描述

官方的demo代码都是写在lv_demo_widgets.c中的,所以我们主要对其中的lv_demo_widgets.c文件进行编程和修改。assets目录中的两个文件是将图像数组化之后生成的C文件,这两个C文件里面包含了图像的像素信息,图像数组化转换的方法会在之后的导入图片步骤中进行介绍。lv_events文件夹是新创建的文件夹,其中的文件声明并定义了各个组件的事件响应函数。

3. 编程目标

本文设计的LVGL GUI界面如下:

在这里插入图片描述

我们只实现上述图片中LED灯控制开关、蜂鸣器控制开关、温湿度实时显示的三个相关功能。其中LED开关开启后,外接的LED灯会被点亮,开关关闭之后灯会熄灭;Buzzer开关开启之后,板载的蜂鸣器会响,

4. 编程前的准备

上一章展示的GUI界面涉及到不同大小的字体,所以在构建我们的程序之前,需要将所有大小的字体使能,我们先打开源码根目录下的文件lv_conf.h,看到第326行,我们将所有字体大小的宏定义全部改为1:

/*Montserrat fonts with ASCII range and some symbols using bpp = 4*https://fonts.google.com/specimen/Montserrat*/
#define LV_FONT_MONTSERRAT_8  1
#define LV_FONT_MONTSERRAT_10 1
#define LV_FONT_MONTSERRAT_12 1
#define LV_FONT_MONTSERRAT_14 1
/*... ...*/
#define LV_FONT_MONTSERRAT_48 1

5. LVGL编程基础

5.1 简单示例代码

下面是一个简单的LVGL编程实例,在一个Label中显示”Hello World!”:

#include "lv_demo_widgets.h"
#include "lv_events/lv_events.h"lv_obj_t              *label_example;void lv_demo_widgets(void){label_example = lv_label_create(lv_scr_act());lv_label_set_text(label_example, "Hello World!");lv_obj_set_style_text_font(label_example, &lv_font_montserrat_24, LV_STATE_DEFAULT);lv_obj_align(label_example,LV_ALIGN_CENTER,0,0);return ;
};

将上述代码在LVGL仿真器中运行,效果如下:

在这里插入图片描述

简要说一下其中代码的逻辑:

  1. label_example = lv_label_create(lv_scr_act());这句代码的作用是创建一个Label组件的对象,lv_label_create就是创建它的函数,其返回值是lv_obj_t *类型,即所有组件对象的指针,其中函数lv_scr_act的作用是让创建的该组件能在屏幕上显示;

  2. lv_label_set_text(label_example, "Hello World!");这句代码的作用是设置Label组件文本的内容,其中第一个参数是创建好的Label对象指针,第二个参数是需要设置的文本内容;

  3. lv_obj_set_style_text_font(label_example, &lv_font_montserrat_24, LV_STATE_DEFAULT); 这句代码的作用是设置Label文本的字体大小,如第4章中头文件所展示的那样,这里的宏lv_font_montserrat_24表示将文本字体大小设置为24;

  4. lv_obj_align(label_example,LV_ALIGN_CENTER,0,0); 这句代码的作用是设置组件对齐。

5.2 设置组件位置

在LVGL的实际运用中,我们有两中方法来设置组件的位置。

  • 第一种是直接指定其在屏幕上的位置坐标,来确定组件的绝对位置,例如:
lv_obj_set_pos(calendar, 511, 32);

上面的代码是设置一个日历(Calendar)组件的坐标位置,函数lv_obj_set_pos原型为void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y),其中第一个参数是已经创建好的组件对象指针,第二和第三个参数分别是横向坐标值和纵向坐标值。

  • 第二种则是通过对齐的方式,来确定组件的相对位置,这时使用的函数为:

void lv_obj_align(lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs)

或者

void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs)

其中第一个函数是组件相对于显示屏对齐,第二个则是组件相对于其他组件进行对齐,形参align表示对齐的方式,LVGL中所有的对齐方式如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0twYRi9V-1685537889428)(/align.png)]

这些对齐方式所对应宏的通用形式为:LV_ALIGN_OUT_XXX 。函数lv_obj_alignlv_obj_align_to 中共有的形参lv_coord_t x_ofs, lv_coord_t y_ofs表示相对于屏幕上的(x_ofs, y_ofs)坐标对齐。

5.3 图片的显示

本节我们讲述将图片lvgl_shallwing.jpg显示到LCD屏上的方法,图片lvgl_shallwing.jpg如下图所示:

在这里插入图片描述

在LVGL显示图片需要先将图片转化为像素数组,其转化的方法如下:

  1. 打开网页链接:LVGL官网;

  2. 点击网页中的”Tools“,并选择其中的Image converter:

在这里插入图片描述

  1. 在弹出的网页中,可以看到在线图片转换器,图片转换器里面有许多选项,如下图所示:

在这里插入图片描述

  1. 我们现在Imgae file中选择需要转化的图片,然后选择图片的色彩格式为CF_TRUE_COLOR(真彩格式),Output format保持为C array不变,然后点击Convert进行转换;

  2. 点击“Convert”之后,网页会自动下载生成好的带有C array的C文件:
    在这里插入图片描述

    我们将生成好的lvgl_shallwing.c文件放在下列LVGL源码中的目录下,以便之后调用该文件中的生成的数组:

./lv_port_linux_frame_buffer/lvgl/demos/widgets/assets

以上就是利用LVGL官方的图片转换器进行图片像素数字化的方法。

先给出在LVGL中显示图片的代码:

void lv_demo_widgets(void){lv_obj_t              *image_shallwing = lv_img_create(lv_scr_act());//Set the image size and the positionlv_img_set_src(image_shallwing, &lvgl_shallwing);lv_obj_set_pos(image_shallwing, 54, 52);return ;
}

这段代码的逻辑很简单,函数lv_img_create的作用是创建一个image图片组件,其使用方法和lv_label_create类似。函数lv_img_set_src用于设置图片的内容,函数lv_img_set_src的第二个参数是图片的像素数组名,图片lvgl_shallwing.jpg转换生成的C文件名称为lvgl_shallwing.c,所以该图片生成的像素数组的数组名叫lvgl_shallwing。函数lv_obj_set_pos的作用是设置图片左上角在界面上的坐标位置,这里我们将坐标设置为(54,52);

将上面的代码编译之后,可以在LVGL模拟器中看到如下效果:

在这里插入图片描述

5.4 组件的事件响应

与其他图形库的编程一样,LVGL也有自己的事件响应机制,LVGL中设置组件事件响应的函数为:

struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,void * user_data)

其中第一个参数obj为创建好的组件对象指针;event_cb是事件处理函数,当组件出发了事件时,就会执行此函数;lv_event_code_t表示事件码,事件码用来指代事件的类型,此形参需要通过具体组件来进行设置;事件响应函数中运行用户自己传入参数,这在形参user_data中有所体现。

LVGL组件中的事件码如下:

/*** Type of event being sent to the object.*/
typedef enum {LV_EVENT_ALL = 0,/** Input device events*/LV_EVENT_PRESSED,             /**< The object has been pressed*/LV_EVENT_PRESSING,            /**< The object is being pressed (called continuously while pressing)*/LV_EVENT_PRESS_LOST,          /**< The object is still being pressed but slid cursor/finger off of the object */LV_EVENT_SHORT_CLICKED,       /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/LV_EVENT_LONG_PRESSED,        /**< Object has been pressed for at least `long_press_time`.  Not called if scrolled.*/LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms.  Not called if scrolled.*/LV_EVENT_CLICKED,             /**< Called on release if not scrolled (regardless to long press)*/LV_EVENT_RELEASED,            /**< Called in every cases when the object has been released*/LV_EVENT_SCROLL_BEGIN,        /**< Scrolling begins. The event parameter is a pointer to the animation of the scroll. Can be modified*/LV_EVENT_SCROLL_END,          /**< Scrolling ends*/LV_EVENT_SCROLL,              /**< Scrolling*/LV_EVENT_GESTURE,             /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */LV_EVENT_KEY,                 /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/LV_EVENT_FOCUSED,             /**< The object is focused*/LV_EVENT_DEFOCUSED,           /**< The object is defocused*/LV_EVENT_LEAVE,               /**< The object is defocused but still selected*/LV_EVENT_HIT_TEST,            /**< Perform advanced hit-testing*//** Drawing events*/LV_EVENT_COVER_CHECK,        /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/LV_EVENT_DRAW_MAIN_BEGIN,    /**< Starting the main drawing phase*/LV_EVENT_DRAW_MAIN,          /**< Perform the main drawing*/LV_EVENT_DRAW_MAIN_END,      /**< Finishing the main drawing phase*/LV_EVENT_DRAW_POST_BEGIN,    /**< Starting the post draw phase (when all children are drawn)*/LV_EVENT_DRAW_POST,          /**< Perform the post draw phase (when all children are drawn)*/LV_EVENT_DRAW_POST_END,      /**< Finishing the post draw phase (when all children are drawn)*/LV_EVENT_DRAW_PART_BEGIN,    /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */LV_EVENT_DRAW_PART_END,      /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. *//** Special events*/LV_EVENT_VALUE_CHANGED,       /**< The object's value has changed (i.e. slider moved)*/LV_EVENT_INSERT,              /**< A text is inserted to the object. The event data is `char *` being inserted.*/LV_EVENT_REFRESH,             /**< Notify the object to refresh something on it (for the user)*/LV_EVENT_READY,               /**< A process has finished*/LV_EVENT_CANCEL,              /**< A process has been cancelled *//** Other events*/LV_EVENT_DELETE,              /**< Object is being deleted*/LV_EVENT_CHILD_CHANGED,       /**< Child was removed, added, or its size, position were changed */LV_EVENT_CHILD_CREATED,       /**< Child was created, always bubbles up to all parents*/LV_EVENT_CHILD_DELETED,       /**< Child was deleted, always bubbles up to all parents*/LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/LV_EVENT_SCREEN_LOAD_START,   /**< A screen load started, fired when the screen change delay is expired*/LV_EVENT_SCREEN_LOADED,       /**< A screen was loaded*/LV_EVENT_SCREEN_UNLOADED,     /**< A screen was unloaded*/LV_EVENT_SIZE_CHANGED,        /**< Object coordinates/size have changed*/LV_EVENT_STYLE_CHANGED,       /**< Object's style has changed*/LV_EVENT_LAYOUT_CHANGED,      /**< The children position has changed due to a layout recalculation*/LV_EVENT_GET_SELF_SIZE,       /**< Get the internal size of a widget*/_LV_EVENT_LAST,               /** Number of default events*/LV_EVENT_PREPROCESS = 0x80,   /** This is a flag that can be set with an event so it's processedbefore the class default event processing */
} lv_event_code_t;

可以看到,LVGL中的事件大致分为输入设备事件(Input device events)、绘图事件(Drawing events)、特殊事件(Special events)以及其他事件四种,且事件码由枚举类型定义。本文需要实现的开关功能则对应于特殊事件中的 LV_EVENT_VALUE_CHANGED,意思就是此枚举与开关事件相关联时,开关组件的状态若发生了改变,系统就会调用事件响应函数进行处理

Button组件按下对应的事件码为LV_EVENT_PRESSED,表示有组件被点击的事件。

我们也可以在自己的程序中某时刻撤销组件的事件响应,撤销事件响应的函数为:

bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)

此函数的返回值类型是bool,若返回false,表示没有在组件中找到形参中的事件响应函数,当返回true时,则表示此时已经成功撤销该事件的响应机制。

后面的章节里会就开关组件事件响应编写对应的代码。

5.5 设置定时任务

在LVGL里,我们可以利用其中的定时机制来周期性完成某些任务,比如后面将会实现的定时20s显示环境温湿度值。

当前现存的一些中文教程中会告诉读者设置定时任务的函数是lv_task_create() ,但这是LVGL 7.0以前的版本使用的,目前的V8.2版本已经将其改为了lv_timer_create()

在这里插入图片描述

这在LVGL源码的./lvgl/docs/overview/timer.md文件中也有说明:

# TimersLVGL has a built-in timer system. You can register a function to have it be called periodically. The timers are handled   and called in `lv_timer_handler()`, which needs to be called every few milliseconds.
See [Porting](/porting/task-handler) for more information.Timers are non-preemptive, which means a timer cannot interrupt another timer. Therefore, you can call any LVGL related   function in a timer. ## Create a timer
To create a new timer, use `lv_timer_create(timer_cb, period_ms, user_data)`. It will create an `lv_timer_t *` variable,  which can be used later to modify the parameters of the timer. 
`lv_timer_create_basic()` can also be used. This allows you to create a new timer without specifying any parameters.

V8.2 版本中设置定时任务的函数lv_timer_create 原型为:

lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data);

其中第一个参数timer_xcb是定时任务所对应的回调函数,第二个参数period是定时周期,第三个参数是用户传入的数据。

6. 各个组件编程的实现

本章节主要就第3章展示的目标,逐个讲述其中各个组件的创建和功能实现。

6.1 文本标签组件(lv_label)

第3章所展示的界面中有如下部分是文本标签组件:

在这里插入图片描述

在第5章已经介绍了文本标签组件的创建和显示,以及字体大小的设置,这里直接给出上面所有文本标签组件相应的代码:

/* The txt label for temperature and humidty are global variables, 
which are used for define event handler. */
static lv_obj_t              *label_temper;
static lv_obj_t              *label_humidity;//...
//...
//...void lv_demo_widgets(void){
/* Create the Label widgets and display on the LCD */    lv_obj_t              *label_lvgl_demo = lv_label_create(lv_scr_act());lv_obj_t              *label_author = lv_label_create(lv_scr_act());lv_obj_t              *label_studio = lv_label_create(lv_scr_act());lv_obj_t              *label_led = lv_label_create(lv_scr_act());lv_obj_t              *label_buzzer = lv_label_create(lv_scr_act());   label_temper = lv_label_create(lv_scr_act());label_humidity = lv_label_create(lv_scr_act());/* Set the position and the text and its size *///"Donald Shallwing"lv_obj_set_pos(label_author, 193, 61);lv_label_set_text(label_author, "Donald Shallwing");lv_obj_set_style_text_font(label_author, &lv_font_montserrat_24, LV_STATE_DEFAULT);//"donaldshallwing@gmail.com"lv_obj_set_pos(label_lvgl_demo, 193, 108);lv_label_set_text(label_lvgl_demo, "donaldshallwing@gmail.com");lv_obj_set_style_text_font(label_lvgl_demo, &lv_font_montserrat_14, LV_STATE_DEFAULT);//"IoT-Yun"lv_obj_set_pos(label_studio, 193, 135);lv_label_set_text(label_studio, "IoT-Yun / CCNU");lv_obj_set_style_text_font(label_studio, &lv_font_montserrat_14, LV_STATE_DEFAULT);// "LED" & "Buzzer"lv_obj_set_pos(label_led, 90, 270);lv_label_set_text(label_led, "LED");lv_obj_set_style_text_font(label_led, &lv_font_montserrat_20, LV_STATE_DEFAULT);lv_obj_set_pos(label_buzzer, 80, 382);lv_label_set_text(label_buzzer, "Buzzer");lv_obj_set_style_text_font(label_buzzer, &lv_font_montserrat_20, LV_STATE_DEFAULT);// Label for temperature & humidty display, set " " for primarylv_obj_set_pos(label_temper, 662, 284);lv_label_set_text(label_temper, " ");lv_obj_set_style_text_font(label_temper, &lv_font_montserrat_22, LV_STATE_DEFAULT);lv_obj_set_pos(label_humidity, 662, 329);lv_label_set_text(label_humidity, " ");lv_obj_set_style_text_font(label_humidity, &lv_font_montserrat_22, LV_STATE_DEFAULT);return ;
}

温湿度需要使用定时任务机制来进行实时获取,而且我们要求温湿度的数值显示在文本标签组件中,所以这里把温湿度对应的文本标签组件变量label_temper与label_humidity设置为全局变量,为了与其他文件中的命名产生冲突,必须在定义时加上static关键字。

6.2 开关组件(lv_switch)

创建显示LED和Buzzer两个开关组件、并设置事件响应的代码如下:

static lv_obj_t              *sw_led;
static lv_obj_t              *sw_buzzer;static void led_event_cb(lv_event_t *e){lv_event_code_t code = lv_event_get_code(e);if(LV_EVENT_VALUE_CHANGED == code){if(lv_obj_has_state(sw_led, LV_STATE_CHECKED))led(true);elseled(false);}return ;
}static void buzzer_event_cb(lv_event_t *e){lv_event_code_t code = lv_event_get_code(e);if(LV_EVENT_VALUE_CHANGED == code){if(lv_obj_has_state(sw_buzzer, LV_STATE_CHECKED))buzzer(true);elsebuzzer(false);}return ;
}void lv_demo_widgets(void){sw_led = lv_switch_create(lv_scr_act());sw_buzzer = lv_switch_create(lv_scr_act());lv_obj_set_pos(sw_led, 83, 234);lv_obj_set_size(sw_led, 60, 30);lv_obj_add_event_cb(sw_led, led_event_cb, LV_EVENT_VALUE_CHANGED, NULL);lv_obj_set_pos(sw_buzzer, 83, 335);lv_obj_set_size(sw_buzzer, 60, 30);lv_obj_add_event_cb(sw_buzzer, buzzer_event_cb, LV_EVENT_VALUE_CHANGED, NULL);return ;
}

LVGL中所有事件的回调函数都具有相同的形参,即lv_event_t *e,在一个会掉函数里,我们首先通过函数lv_event_get_code取得事件码(lv_event_code_t),如果事件码与lv_obj_add_event_cb中添加的事件码一直,则运行后面的处理程序。我们可以看到在回调函数led_event_cb中,通过函数lv_obj_has_state取得开关的状态之后,如果此时开关是开启的,则通过自定的函数led来点亮LED灯,函数led的代码在第二章中所述的文件lv_events.c中。

蜂鸣器的事件响应函数逻辑与LED灯是一样的。

6.3 图片按键组件(lv_btn)

第3章里展示的温湿度logo是一个图片按键组件,从本质上来看,它和普通的Button没什么区别,其创建显示,以及事件响应的代码如下:

static lv_obj_t              *image_temper;#if USE_IMGBTN_EVENT
static void sht20_event_cb(lv_event_t *e){double               temperature, humidity;char				 buffer[32] = {0};lv_event_code_t code = lv_event_get_code(e);if(LV_EVENT_PRESSED == code){sht20(&temperature, &humidity);sprintf(buffer, "%.2lf 'C", temperature);lv_label_set_text(label_temper, buffer);memset(buffer, 0, sizeof(buffer));sprintf(buffer, "%.2lf %%", humidity);lv_label_set_text(label_humidity, buffer);}return ;
}
#endifvoid lv_demo_widgets(void){//Image for temperature & humiditylv_imgbtn_set_src(image_temper, LV_IMGBTN_STATE_RELEASED,NULL, &lvgl_temper, NULL);lv_obj_set_size(image_temper, 80, 100);lv_obj_set_pos(image_temper, 557, 267);#if USE_IMGBTN_EVENTlv_obj_add_event_cb(image_temper, sht20_event_cb, LV_EVENT_PRESSED, NULL);#endifreturn ;
}

上述代码中回调函数的逻辑是:当该图片按键按下之后,系统会通过函数sht20读取当前sht20温湿度传感器中的温湿度值,然后在文本标签组件label_temperlabel_humidity中进行显示。

我们这里只是演示一下图片按键的用法,在这个项目里面,我们并不是通过图片按键按下的方式获取温湿度值,而是设置定时任务实时显示,所以这里我们将上述代码中的宏USE_IMGBTN_EVENT定义为0。

6.4 设置定时任务(lv_timer)

由于在5.5小节已经讲述了定时任务的设置方法,这里直接给出其中温湿度实时显示的代码:

static void sht20_task(lv_timer_t *timer){double               temperature, humidity;char				 buffer[32] = {0};sht20(&temperature, &humidity);sprintf(buffer, "%.2lf 'C", temperature);lv_label_set_text(label_temper, buffer);memset(buffer, 0, sizeof(buffer));sprintf(buffer, "%.2lf %%", humidity);lv_label_set_text(label_humidity, buffer);return ;
}void lv_demo_widgets(void){timer_sht20 = lv_timer_create(sht20_task, 1000*20, NULL);return ;
}

我们将温湿度读取的时间间隔设置为20s。

6.5 显示其他组件

第三章中所展示的日历(lv_calendar)和图表(lv_chart)组件我们只做了显示,没有实现其事件响应,此工作留在之后的文档中完成。显示日历和图表的代码如下:

static lv_obj_t              *calendar = lv_calendar_create(lv_scr_act());
static lv_obj_t              *temper_chart = lv_chart_create(lv_scr_act());void lv_demo_widgets(void){//Calendarlv_obj_set_pos(calendar, 511, 32);lv_obj_set_size(calendar, 205, 155);//Chartlv_obj_set_pos(temper_chart, 245, 222);lv_obj_set_size(temper_chart, 254, 190);return ;
}

7. 代码测试

将上述代码在Linux下通过源码的主Makefile交叉编译之后,然后通过TFTP将可执行文件传输到IMX6ULL开发板上,进行如下测试:

  1. 若执行之后显示的效果和仿真一样,则说明组件的创建与显示部分正常;
  2. 若在点击LED的开关之后,LED灯被点亮,且再次按下开关之后,LED灯熄灭,则说明LED事件响应函数设置正确;
  3. 若在点击蜂鸣器的开关之后,板载蜂鸣器发出声响,且再次按下开关之后,不再发声,则说明蜂鸣器事件响应函数设置正确;
  4. 若在屏幕上每隔20s能看到温湿度在更新,则说明实时过去温湿度的功能已经实现。

8. 工程源码

本工程的所有源码已在Gitee上给出,链接如下:
lvgl-lcd
由于点亮LED灯和使能蜂鸣器的代码不属于LVGL编程的范围,故此代码未在文档中展示。

参考文档

【LVGL事件(Events)】事件代码
在CodeBlock中实现LVGL模拟仿真


http://www.ppmy.cn/news/127318.html

相关文章

变频冰箱变频空调

有开发过变频冰箱&#xff0c;变频空调。的工程师私信我&#xff0c;有项目可以对接。

变频

VC&#xff1a;有PG矢量控制 SVC&#xff1a;无PG矢量控制 TC&#xff1a;转矩控制 调速比&#xff1a;电机额定50Hz&#xff0c;控制器能够保证0.05Hz都满转矩&#xff0c;可以说调速范围是1:1000 变频器的主回路图 输入电源&#xff0c;启动电阻&#xff0c;整流&#xf…

北京东城区空调维修办法,格力变频空调出现ph,到底是怎么回事?

空调由于是提供给我们人类便利的机器&#xff0c;所以正常的时候&#xff0c;一切都好&#xff0c;如果哪里有异常时候&#xff0c;就会出现各种各样奇怪难懂的代码&#xff0c;对于我们这种常规用户来说&#xff0c;根本看不懂这些代码有代表什么意思&#xff0c;这些代码究竟…

变频空调的基本原理

目前&#xff0c;常见的变频方式主要有交流变频和直流变频两种。 1.交流变频 交流变频器主要由AC-DC变换器(整流、滤波电路)、三相逆变器(inverter电路)、脉冲宽度调制电路(PWM电路)构成&#xff0c;如图1-1所示。 首先&#xff0c;AC-DC变换器将220V市电电压变换为310V左右…

美的空调室外机工作异常综合案例分析与检修

【例1】 美的KFR-32GW/BM&#xff08;F&#xff09;型变频空调开机室内机工作&#xff0c;但室外机不工作分析与检修&#xff1a;通过故障现象分析&#xff0c;说明室外机电源电路、微处理器电路或被保护的电路异常。通过自诊断&#xff0c;显示2号灯亮&#xff0c;1、3号灯灭…

美的变频空调制冷/制热异常故障分析与检修案例

【例1】 美的KFR-28GW/BpY-R型变频空调制冷效果差&#xff08;一&#xff09; 分析与检修&#xff1a;通过故障现象分析&#xff0c;怀疑故障是由于制冷系统、通风系统、温度检测电路或微处理器电路异常所致。检查通风系统正常&#xff0c;测制冷系统的压力正常&#xff08;为…

变频空调特有器件

变频空调的特有器件主要是变频压缩机、智能功率模块和电子胀阀3种。 一、变频压缩机 变频压缩机是变频空调的核心部件按机械结构的不同&#xff0c;可分为涡旋式压缩机和双转子旅转式压缩机两种:按电气结构可分为交流变频压缩机和直流供电变频压缩机两种。下面介绍它们的电气…

idea连接HiveServer2

一、 启动hive 启动hive的元数据服务 [aahadoop102 hive]$ bin/hive --service metastore根据你hive的配置方式启动hiveserver2 [aahadoop102 hive]$ bin/hive --service hiveserver2二、配置idea连接Hive服务 打开idea&#xff0c;在项目界面中的右边栏找到Database&#…