在vscode中,按ctrl+shift+p键打开命令面板,输入搜索“show examples projects”,点击ESP-IDF:展示示例项目,选择你所用的esp-idf版本后,将打开esp-idf的例程创建界面。我这里esp-idf的版本是4.3.2。然后随便选个最简单的hello_world作为创建模板就可以了
打开上一步创建的hello_world目录,新建一个“components”目录
然后将lvgl和lvgl_esp32_drivers两个仓库的最新代码clone到components目录内
https://github.com/lvgl/lvgl
https://github.com/lvgl/lvgl_esp32_drivers
现在的工程目录结构应该是这样的
在lvgl的目录下,有一个lv_conf_template.h的模板头文件,将其复制到同目录内,重命名为lv_conf.h。然后将里面最开始的“#if 0”改为“#if 1”使其生效,其它的都不用动了。在后面的menucofig后,相关的配置会作用里面的各种宏定义。
这里直接贴代码
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_freertos_hooks.h"
#include "../components/lvgl/lvgl.h"
#include "lvgl_helpers.h"
/*-----------------函数声明-----------------------------------*/
void lvgl_test(void);
/*-----------------------------------------------------------*/
/* LVGL 移植部分 */
static void lv_tick_task(void *arg)
{
(void)arg;
lv_tick_inc(portTICK_PERIOD_MS);
}
SemaphoreHandle_t xGuiSemaphore;
/* UI 任务 */
static void gui_task(void *arg)
{
xGuiSemaphore = xSemaphoreCreateMutex();
lv_init(); //lvgl内核初始化
lvgl_driver_init(); //lvgl显示接口初始化
static lv_disp_draw_buf_t draw_buf;
lv_color_t *buf1 = heap_caps_malloc(LV_HOR_RES_MAX * LV_VER_RES_MAX * sizeof(lv_color_t), MALLOC_CAP_DMA);
lv_color_t *buf2 = heap_caps_malloc(LV_HOR_RES_MAX * LV_VER_RES_MAX * sizeof(lv_color_t), MALLOC_CAP_DMA);
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/
static lv_disp_drv_t disp_drv; /*A variable to hold the drivers. Must be static or global.*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.draw_buf = &draw_buf; /*Set an initialized buffer*/
disp_drv.flush_cb = disp_driver_flush; /*Set a flush callback to draw to the display*/
disp_drv.hor_res = 128; /*Set the horizontal resolution in pixels*/
disp_drv.ver_res = 160; /*Set the vertical resolution in pixels*/
lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/
esp_register_freertos_tick_hook(lv_tick_task);
lvgl_test();
while (1)
{
/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
vTaskDelay(pdMS_TO_TICKS(10));
/* Try to take the semaphore, call lvgl related function on success */
if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
{
lv_timer_handler();
xSemaphoreGive(xGuiSemaphore);
}
}
}
// lvgl测试
void lvgl_test(void)
{
lv_obj_t *label1 = lv_label_create(lv_scr_act());
lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/
lv_label_set_recolor(label1, true); /*Enable re-coloring by commands in the text*/
lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label, align the lines to the center"
"and wrap long text automatically.");
lv_obj_set_width(label1, 120); /*Set smaller width to make the lines wrap*/
lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_align(label1, LV_ALIGN_CENTER, 0, -40);
lv_obj_t *label2 = lv_label_create(lv_scr_act());
lv_label_set_long_mode(label2, LV_LABEL_LONG_SCROLL_CIRCULAR); /*Circular scroll*/
lv_obj_set_width(label2, 120);
lv_label_set_text(label2, "It is a circularly scrolling text. ");
lv_obj_align(label2, LV_ALIGN_CENTER, 0, 40);
}
// 主函数
void app_main(void)
{
xTaskCreatePinnedToCore(gui_task, "gui task", 1024 * 3, NULL, 1, NULL, 0);
}
然后menuconfig,根据自己需要配置(可参考之前的移植blog)
这里有点要注意,因为我没有导入lvgl的examples工程,所以“Enable the examples to be built”这个就不要勾选了。
最后点击编译。
理所当然是肯定会报错的。这些开源该死的频繁更新。。。
1、‘SPI_HOST_MAX’ undeclared (first use in this function); did you mean ‘GPIO_PORT_MAX’?"
位于lvgl_esp32_drivers内的lvgl_helpers.c,直接粗暴将这句“assert((0 <= host) && (SPI_HOST_MAX > host))”注释掉就行了
bool lvgl_spi_driver_init(int host,
int miso_pin, int mosi_pin, int sclk_pin,
int max_transfer_sz,
int dma_channel,
int quadwp_pin, int quadhd_pin)
{
// assert((0 <= host) && (SPI_HOST_MAX > host));
const char *spi_names[] = {
"SPI1_HOST", "SPI2_HOST", "SPI3_HOST"
};
2、‘DLV_HOR_RES_MAX’ undeclared (first use in this function); did you mean ‘LV_HOR_RES’?
‘DLV_VER_RES_MAX’ undeclared (first use in this function); did you mean ‘LV_VER_RES’?
lvgl_helpers.h缺少这两个宏定义,加上
* When using RGB displays the display buffer size will also depends on the
* color format being used, for RGB565 each pixel needs 2 bytes.
* When using the mono theme, the display pixels can be represented in one bit,
* so the buffer size can be divided by 8, e.g. see SSD1306 display size. */
#define LV_HOR_RES_MAX 240
#define LV_VER_RES_MAX 240
#if defined (CONFIG_CUSTOM_DISPLAY_BUFFER_SIZE)
#define DISP_BUF_SIZE CONFIG_CUSTOM_DISPLAY_BUFFER_BYTES
3、好了,编译通过了,是不是这就完了?不,Too young too simple。
程序启动时报错,然后不断重启。。。
又是一番爬之后,改这里吧:
还是lvgl_helpers.h这个文件。不知到为社么,显示缓存大小的计算定义在新版本中被改成了水平宽度x40了。我的是ST7735S,这里改成水平x垂直
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#define LV_HOR_RES_MAX 240
#define LV_VER_RES_MAX 240
#if defined (CONFIG_CUSTOM_DISPLAY_BUFFER_SIZE)
#define DISP_BUF_SIZE CONFIG_CUSTOM_DISPLAY_BUFFER_BYTES
#else
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)