在这篇博客中,我们将根据 esp-iot-solution 中的示例 lvgl_example 和 LittlevGL 中的示例 littlevgl/lv_sim_eclipse_sdl。我们在这里使用的 esp-iot-solution 版本 commit为: 40cec13
可通过以下命令确认:
git log --oneline -1
结果为:
40cec13 Merge branch 'master' of https://github.com/espressif/esp-iot-solution
lv_sim_eclipse_sdl 可以无需使用开发板,直接在 PC 端上模拟运行 LittlevGL,具体教程见 ESP32 快速入门(五): LittlevGL PC Simulator 使用入门。
如果需要了解具体的 LittlevGL 向导,请参考 LittlevGL Guide。
我们先查看 app_main 函数:
extern "C" void app_main()
{
/* Initialize LittlevGL GUI */
lvgl_init();
#ifdef LVGL_EXAMPLE
/* littlevgl demo */
littlevgl_demo();
xTaskCreate(
user_task, //Task Function
"user_task", //Task Name
1024, //Stack Depth
NULL, //Parameters
1, //Priority
NULL); //Task Handler
#endif
#ifdef LVGL_TEST_THEME
lv_theme_t *th = lv_theme_alien_init(100, NULL);
lv_test_theme_1(th);
#endif
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
}
此示例首先使用 lvgl_init()
函数来初始化 LittlevGL,然后通过两个 ifdef 来决定是否进入 LVGL_EXAMPLE 示例与 LVGL_TEST_THEME 示例。在这里,我们可以分别查看这两个示例的具体内容。
注意:使用 LittlevGL 时别忘了添加对应的头文件,在程序开头添加
#include "iot_lvgl.h"
。
在上述的 app_main 函数中,我们可以看到此函数里运行了 littlevgl_demo()
函数配置 demo 与 xTaskCreate()
函数来创建任务进行定时刷新数据。
在此函数中,首先就是 screen 等对象的创建:
lv_obj_t *scr = lv_obj_create(NULL, NULL);
lv_scr_load(scr);
lv_theme_t *th = lv_theme_alien_init(100, NULL);
lv_theme_set_current(th);
lv_obj_t *tabview = lv_tabview_create(lv_scr_act(), NULL);
lv_obj_t *tab1 = lv_tabview_add_tab(tabview, SYMBOL_LOOP);
lv_obj_t *tab2 = lv_tabview_add_tab(tabview, SYMBOL_HOME);
lv_obj_t *tab3 = lv_tabview_add_tab(tabview, SYMBOL_SETTINGS);
lv_tabview_set_tab_act(tabview, 1, false);
我们可以看到这段代码创建了 screen,theme 和 tab 对象,并设置了初始状态。然后此示例就开始在添加的三个 tab 中进行进一步的操作,在这里我们以后续的 tab 2 为例:
chart = lv_chart_create(tab2, NULL);
lv_obj_set_size(chart, 300, 150);
lv_chart_set_point_count(chart, 20);
lv_obj_align(chart, NULL, LV_ALIGN_CENTER, 0, 0);
lv_chart_set_type(chart, (lv_chart_type_t)(LV_CHART_TYPE_POINT | LV_CHART_TYPE_LINE));
lv_chart_set_series_opa(chart, LV_OPA_70);
lv_chart_set_series_width(chart, 4);
lv_chart_set_range(chart, 0, 100);
series = lv_chart_add_series(chart, LV_COLOR_RED);
我们可以看到这里创建了一个 chart,然后将 chart 的一系列属性进行设置,比如 size, type, range 等。
我们日常先看相关代码:
static void user_task(void *pvParameter)
{
uint8_t value = 0;
while (1)
{
value = esp_random() % 100;
lv_chart_set_next(chart, series, value);
lv_gauge_set_value(gauge, 0, value);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
在这段代码中,我们可以发现此任务每隔 500 ms 就设置新的 chart 和 gauge 值,设置的值 value 通过 esp_random() % 100
随机生成。
在上述的 app_main 函数中,我们可以看到此函数里运行了 lv_theme_alien_init()
函数与 lv_test_theme_1()
函数。
这个函数主要就是 fond 与 style 的配置,然后再初始化一系列需要用到的组件,比如 gauge_init()
与 btn_init()
等。
这函数里的内容较少,所以我们直接贴出代码:
void lv_test_theme_1(lv_theme_t * th)
{
lv_theme_set_current(th);
th = lv_theme_get_current(); /*If `LV_THEME_LIVE_UPDATE 1` `th` is not used directly so get the real theme after set*/
lv_obj_t * scr = lv_cont_create(NULL, NULL);
lv_scr_load(scr);
lv_cont_set_style(scr, th->bg);
lv_obj_t * tv = lv_tabview_create(scr, NULL);
lv_obj_set_size(tv, LV_HOR_RES, LV_VER_RES);
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "Tab 1");
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "Tab 2");
lv_obj_t * tab3 = lv_tabview_add_tab(tv, "Tab 3");
create_tab1(tab1);
create_tab2(tab2);
create_tab3(tab3);
}
这个函数的功能是创建一个包含很多对象的测试屏幕,并在其上应用给定的主题。比如他创建了一个 screen 对象,在此基础上又创建了 tabview 等。
我们仍然直接查看 main 函数:
int main(int argc, char ** argv)
{
(void) argc; /*Unused*/
(void) argv; /*Unused*/
/*Initialize LittlevGL*/
lv_init();
/*Initialize the HAL (display, input devices, tick) for LittlevGL*/
hal_init();
/*Create a demo*/
demo_create();
while(1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
usleep(5 * 1000);
#ifdef SDL_APPLE
SDL_Event event;
while(SDL_PollEvent(&event)) {
#if USE_MOUSE != 0
mouse_handler(&event);
#endif
#if USE_KEYBOARD
keyboard_handler(&event);
#endif
#if USE_MOUSEWHEEL != 0
mousewheel_handler(&event);
#endif
}
#endif
}
return 0;
}
我们可以很清晰地看出首先通过 lv_init()
和 hal_init()
进行了 LittlevGL 和 HAL 的初始化。然后就使用 demo_create()
函数创建 demo,在这个函数中与 lvgl_example 示例类似,也是初始化一些基础参数和 img,tabview 等对象的创建与配置,最后通过 while(1)
循环检测是否使用了 mouse, keyboard 和 mousewheel。