前言
基于ESP32 IDF框架移植的LVGL,IDF版本为4.3.1,LVGL版本为8.1.1。屏幕为中景园的1.47寸172x320分辨率的圆角IPS,驱动芯片为st7789v3。
B站视频效果:
在lvgl_esp32_drivers文件夹下,有个lvgl_tft文件夹,其中找到st7789.c、st7789.h驱动文件。修改屏幕起始像素偏移量offsety1、offsety2,即加上34。
void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{
uint8_t data[4] = {0};
uint16_t offsetx1 = area->x1;
uint16_t offsetx2 = area->x2;
uint16_t offsety1 = area->y1;
uint16_t offsety2 = area->y2;
offsety1 += 34;
offsety2 += 34;
#if (CONFIG_LV_TFT_DISPLAY_OFFSETS)
offsetx1 += CONFIG_LV_TFT_DISPLAY_X_OFFSET;
offsetx2 += CONFIG_LV_TFT_DISPLAY_X_OFFSET;
offsety1 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET;
offsety2 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET;
#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 240)
#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
offsetx1 += 80;
offsetx2 += 80;
#elif (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)
offsety1 += 80;
offsety2 += 80;
#endif
#endif
/*Column addresses*/
st7789_send_cmd(ST7789_CASET);
data[0] = (offsetx1 >> 8) & 0xFF;
data[1] = offsetx1 & 0xFF;
data[2] = (offsetx2 >> 8) & 0xFF;
data[3] = offsetx2 & 0xFF;
st7789_send_data(data, 4);
/*Page addresses*/
st7789_send_cmd(ST7789_RASET);
data[0] = (offsety1 >> 8) & 0xFF;
data[1] = offsety1 & 0xFF;
data[2] = (offsety2 >> 8) & 0xFF;
data[3] = offsety2 & 0xFF;
st7789_send_data(data, 4);
/*Memory write*/
st7789_send_cmd(ST7789_RAMWR);
size_t size = (size_t)lv_area_get_width(area) * (size_t)lv_area_get_height(area);
st7789_send_color((void*)color_map, size * 2);
}
同样在lvgl_esp32_drivers文件夹下找到lvgl_helpers.h文件,增加两个屏幕横向和纵向最大值宏定义。
#define LV_HOR_RES_MAX 320
#define LV_VER_RES_MAX 172
同时在下面的条件编译选项中修改一下DISP_BUF_SIZE。
#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 * LV_VER_RES_MAX)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#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)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
#if defined (CONFIG_LV_THEME_MONO)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8))
#else
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#endif
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#define DISP_BUF_LINES 40
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * DISP_BUF_LINES)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820)
#define DISP_BUF_SIZE (LV_VER_RES_MAX * IL3820_COLUMNS)
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 5KB
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#else
#error "No display controller selected"
#endif
#endif
同样在lvgl_esp32_drivers文件夹下找到lvgl_spi_conf.h文件,修改一下SPI模式。
#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)
#define SPI_TFT_SPI_MODE (3)
#else
#define SPI_TFT_SPI_MODE (0)
#endif
接下来配置LVGL。
在主函数中添加lv_demo_music()例程。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_freertos_hooks.h"
#include "lvgl.h"
#include "lvgl_helpers.h"
#include "arc.h"
#include "bar.h"
#include "lv_examples/src/lv_demo_music/lv_demo_music.h"
void lv_tick_task(void *arg);
static void guiTask(void *pvParameter);
SemaphoreHandle_t xGuiSemaphore;
static void guiTask(void *pvParameter)
{
(void) pvParameter;
xGuiSemaphore = xSemaphoreCreateMutex();
lv_init();
lvgl_driver_init();
lv_color_t* buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1 != NULL);
lv_color_t *buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf2 != NULL);
static lv_disp_draw_buf_t disp_buf;
uint32_t size_in_px = DISP_BUF_SIZE;
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, size_in_px);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = disp_driver_flush;
disp_drv.hor_res = 320;
disp_drv.ver_res = 172;
disp_drv.draw_buf = &disp_buf;
lv_disp_drv_register(&disp_drv);
esp_register_freertos_tick_hook((void *)lv_tick_task);
/* Create the demo application */
//arc_demo_test();
//bar_demo_test();
lv_demo_music();
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);
}
}
/* A task should NEVER return */
free(buf1);
free(buf2);
vTaskDelete(NULL);
}
void app_main(void)
{
xTaskCreatePinnedToCore(guiTask, "gui", 4096 * 4, NULL, 0, NULL, 1);
}
void lv_tick_task(void *arg)
{
(void)arg;
lv_tick_inc(portTICK_PERIOD_MS);
}
详细的移植教程请移步B站专栏!