异常
- 基于VScode ESP-IDF 4.4.5 移植LVGL 8.3.0版本,启动后液晶屏出现花屏现象,运行LVGL demo 会出现拉窗帘现象
环境说明
-
下载 lvgl :
https://github.com/lvgl/lvgl/tree/release/v8.3 -
下载lvgl_esp32_drivers(master 分支):
https://github.com/lvgl/lvgl_esp32_drivers/tree/master
- 移植参考
https://blog.csdn.net/weixin_43326110/article/details/126314659
分析过程
- 液晶屏驱动程序,未使用LVGL下已经调试成功,可以正常使用,该液晶屏使用的驱动芯片为(ST7789V),和lvgl_esp32_drivers 库中的驱动型号不一致
- 对比st7789_init_cmds 配置寄存器信息,修正lvgl_esp32_drivers 库 中st7789.c 中的配置寄存器表
lcd_init_cmd_t st7789_init_cmds[] = {
{0x11, {0}, 0x80},
{0x3A, {0x05},1},
{0xB2, {0x0c,0x0c,0x00,0x33,0x33},5},
{0xB7, {0x35}, 1},
{0xBB, {0x32}, 1},
{0xC2, {0x01}, 1},
{0xC3, {0x15}, 1},
{0xC4, {0x20}, 1},
{0xC6, {0x0F}, 1},
{0xD0, {0xA4,0xA1}, 2},
{ST7789_PVGAMCTRL, {0xD0, 0x08, 0x0E, 0x09, 0x09, 0x05, 0x31, 0x33, 0x48, 0x17, 0x14, 0x15, 0x31, 0x34}, 14},
{ST7789_NVGAMCTRL, {0xD0, 0x08, 0x0E, 0x09, 0x09, 0x15, 0x31, 0x33, 0x48, 0x17, 0x14, 0x15, 0x31, 0x34}, 14},
#if ST7789_INVERT_COLORS == 1
{ST7789_INVON, {0}, 0}, // set inverted mode
#else
{ST7789_INVOFF, {0}, 0}, // set non-inverted mode
#endif
{ST7789_DISPON, {0}, 0x80},
{0, {0}, 0xff},
};
- 分析spi 初始化,查看lv_spi_conf.h文件
// XXX: 修改SPI MODE
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
#define SPI_TFT_SPI_MODE (3)
#else
#define SPI_TFT_SPI_MODE (0)
#endif
- DISP_BUF_SIZE 大小踩坑(维持不动即可)
// 如果设置成 分辨率大小 会出现闪屏现象
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
// 维持不动则不会有异常 (这里表示 不理解)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
- 初始化需增加y方向偏移(官方提供的资料是 240300 尺寸的,实际使用的是 240280)
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
disp_drv.offset_x = 0;
// 设置成 20 (增加偏移)
disp_drv.offset_y = 20;
disp_drv.flush_cb = disp_driver_flush;
disp_drv.draw_buf = &disp_buf;
#if defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT || defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
disp_drv.rotated = 1;
#endif
// disp_drv.full_refresh = 1;
lv_disp_drv_register(&disp_drv);
应用参考
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_timer.h"
/* Littlevgl specific */
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#include "demos/lv_demos.h"
#else
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#endif
#include "lvgl_helpers.h"
#include "lvgl/src/hal/lv_hal_disp.h"
static const char *TAG = "example";
#define LV_TICK_PERIOD_MS 1
static void create_demo_application(void);
void lv_tick_task(void *arg)
{
lv_tick_inc(LV_TICK_PERIOD_MS);
}
SemaphoreHandle_t xGuiSemaphore;
static void lvgl_gui_task(void *pvParameter)
{
xGuiSemaphore = xSemaphoreCreateMutex();
lv_init();
lvgl_driver_init();
static lv_disp_draw_buf_t disp_buf;
lv_color_t *buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t) , MALLOC_CAP_DMA);
lv_color_t *buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t) , MALLOC_CAP_DMA);
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, DISP_BUF_SIZE); /*Initialize the display buffer*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
disp_drv.offset_x = 0;
disp_drv.offset_y = 20;
disp_drv.flush_cb = disp_driver_flush;
disp_drv.draw_buf = &disp_buf;
#if defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT || defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
disp_drv.rotated = 1;
#endif
// disp_drv.full_refresh = 1;
lv_disp_drv_register(&disp_drv);
const esp_timer_create_args_t periodic_timer_args = {
.callback = &lv_tick_task,
.name = "periodic_gui"};
esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000));
// lv_disp_set_bg_color(lv_disp_get_default(),lv_color_make(0xFF,0x0,0x0));
// /* Create the demo application */
// vTaskDelay(pdMS_TO_TICKS(50));
create_demo_application();
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_task_handler();
xSemaphoreGive(xGuiSemaphore);
}
}
}
static void create_demo_application(void)
{
// lv_demo_music();
lv_demo_benchmark();
}
void app_main(void)
{
size_t ram = heap_caps_get_free_size(MALLOC_CAP_DMA);
ESP_LOGW(TAG, "dram=%dkb", ram/1024);
ram = heap_caps_get_free_size(MALLOC_CAP_8BIT);
ESP_LOGW(TAG, "psram=%dkb", ram/1024);
xTaskCreatePinnedToCore(lvgl_gui_task, "gui", 4096*4, NULL, 0, NULL, 1);
}