ESP32入门-移植LVGL显示music的demo

本文介绍如何在ESP32开发板上集成LVGL图形库,并配置2.4寸TFT LCD屏幕显示。主要内容包括硬件连接、软件配置步骤、LVGL文件修改等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.硬件

1.硬件设计
① 开发板型号:ESP32-WROOM-32

2.显示屏幕:
① 2.4寸液晶屏2.4寸TFT LCD SPI串口240*320模块TFT彩屏ST7789驱动
本次2.4寸显示器链接

2.软件设计

2.1 创建一个示例项目

1.怎么创建一个示例项目和创建lvgl组件,添加后先编译,确保创建示例没有问题,请参考前面的文档。

2.2 添加lvgl相关文件

2.2.1 下载相关文件

1.下载lvgl/lvgl中的release/v8.3
在这里插入图片描述
下载lvgl v8.3链接

2.需要下载ESP32的驱动程序
在这里插入图片描述
下载ESP32的驱动程序链接

2.2.2配置components的文件

① 找到项目的 components/lvgl 文件夹,将上面下载的文件解压到 components/lvgl 中,
并将
lvgl_esp32_drivers-master —> lvgl_esp32_drivers
lvgl-release-v8.3 —> lvgl
② 在示例中的components/lvgl/lvgl-release-v8.3/examples中的porting复制到lvgl中,重命名为lvgl_porting。
如下:
在这里插入图片描述

2.2.3添加CMakeLists.txt的文件

1.添加CMakeLists.txt文件相当于告诉编译器文件到哪里去找。

2.在lvgl_porting文件中添加CMakeLists.txt内容如下:

file(GLOB_RECURSE SOURCES 	./*.c 
							)

idf_component_register(SRCS	${SOURCES}
                   INCLUDE_DIRS 
								.
                    REQUIRES  lvgl
                              lvgl_esp32_drivers)

3.修改顶层CMakeLists.txt中添加如下:

set(EXTRA_COMPONENT_DIRS "${EXTRA_COMPONENT_DIRS} components/lvgl")

在这里插入图片描述
4.顶层Makefile中添加
在这里插入图片描述

EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/components/lvgl

5.在项目中找到components/lvgl/env_support/cmake/esp.cmake 代码如下:

file(GLOB_RECURSE SOURCES ${LVGL_ROOT_DIR}/src/*.c
                        ${LVGL_ROOT_DIR}/demos/*.c)

idf_build_get_property(LV_MICROPYTHON LV_MICROPYTHON)

if(LV_MICROPYTHON)
  idf_component_register(
    SRCS
    ${SOURCES}
    INCLUDE_DIRS
    ${LVGL_ROOT_DIR}
    ${LVGL_ROOT_DIR}/src
    ${LVGL_ROOT_DIR}/../
    ${LVGL_ROOT_DIR}/demos
    REQUIRES
    main)

  target_compile_definitions(${COMPONENT_LIB}
                             INTERFACE "-DLV_CONF_INCLUDE_SIMPLE")

  if(CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM)
    target_compile_definitions(${COMPONENT_LIB}
                               INTERFACE "-DLV_ATTRIBUTE_FAST_MEM=IRAM_ATTR")
  endif()
else()
  idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${LVGL_ROOT_DIR}
                         ${LVGL_ROOT_DIR}/src ${LVGL_ROOT_DIR}/../ ${LVGL_ROOT_DIR}/demos)

  target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_CONF_INCLUDE_SIMPLE")

  if(CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM)
    target_compile_definitions(${COMPONENT_LIB}
                               PUBLIC "-DLV_ATTRIBUTE_FAST_MEM=IRAM_ATTR")
  endif()
endif()

在这里插入图片描述

2.3 配置lvgl文件程序和配置

2.3.1配置lvgl文件程序

1.将 lvgl_porting中 的 lv_port_disp_template.c 改为 lv_port_disp.c 并将#if 0 改为#if 1 如下:

#if 1
#include "lv_port_disp_template.h"
#include <stdbool.h>
....
#endif

2.将 lvgl_porting 中的 lv_port_disp_template.h 改为 lv_port_disp.h中 #if 0 改为#if 1 如下:

#if 1
#ifndef LV_PORT_DISP_TEMPL_H
#define LV_PORT_DISP_TEMPL_H
...
#endif

3.将lvgl_esp32_drivers中 lvgl_helpers.h 中修改:

#if defined (CONFIG_CUSTOM_DISPLAY_BUFFER_SIZE)
#define DISP_BUF_SIZE   CONFIG_CUSTOM_DISPLAY_BUFFER_BYTES
#else
//添加部分
#ifndef LV_HOR_RES_MAX
#define LV_HOR_RES_MAX (320)
#endif
#ifndef LV_VER_RES_MAX
#define LV_VER_RES_MAX (240)
#endif
//end

#if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789)

4.将lvgl_esp32_drivers中 lvgl_helpers.c 中修改如下:

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"
    // };
    #if defined(CONFIG_IDF_TARGET_ESP32)
    assert((SPI_HOST <= host) && (VSPI_HOST >= host));
    const char *spi_names[] = {
        "SPI_HOST", "HSPI_HOST", "VSPI_HOST"};

    dma_channel = SPI_DMA_CH_AUTO;
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
    assert((SPI_HOST <= host) && (HSPI_HOST >= host));
    const char *spi_names[] = {
        "SPI_HOST", "", ""};

    dma_channel = SPI_DMA_CH_AUTO;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
    assert((SPI1_HOST <= host) && (SPI3_HOST >= host));
    const char *spi_names[] = {
        "SPI1_HOST", "SPI2_HOST", "SPI3_HOST"};

    dma_channel = SPI_DMA_CH_AUTO; /* SPI_DMA_CH_AUTO */;
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
    assert((SPI1_HOST <= host) && (SPI3_HOST >= host));
    const char *spi_names[] = {
        "SPI_HOST", "HSPI_HOST", "VSPI_HOST"};
    dma_channel = SPI_DMA_CH_AUTO;
#else
#error "Target chip not selected"
#endif

    ESP_LOGI(TAG, "Configuring SPI host %s", spi_names[host]);
    ESP_LOGI(TAG, "MISO pin: %d, MOSI pin: %d, SCLK pin: %d, IO2/WP pin: %d, IO3/HD pin: %d",
        miso_pin, mosi_pin, sclk_pin, quadwp_pin, quadhd_pin);

    ESP_LOGI(TAG, "Max transfer size: %d (bytes)", max_transfer_sz);

    spi_bus_config_t buscfg = {
        .miso_io_num = miso_pin,
        .mosi_io_num = mosi_pin,
        .sclk_io_num = sclk_pin,
        .quadwp_io_num = quadwp_pin,
        .quadhd_io_num = quadhd_pin,
        .max_transfer_sz = max_transfer_sz
    };

    ESP_LOGI(TAG, "Initializing SPI bus...");
    #if defined (CONFIG_IDF_TARGET_ESP32C3)
    dma_channel = SPI_DMA_CH_AUTO;
    #endif
    esp_err_t ret = spi_bus_initialize(host, &buscfg, (spi_dma_chan_t)dma_channel);
    assert(ret == ESP_OK);

    return ESP_OK != ret;
}

4.将lvgl_porting中 lv_port_disp.c 中修改如下:

//1.删除
// #ifndef MY_DISP_HOR_RES
//     #warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
//     #define MY_DISP_HOR_RES    320
// #endif

// #ifndef MY_DISP_VER_RES
//     #warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen height, default value 240 is used for now.
//     #define MY_DISP_VER_RES    240
// #endif

//2.修改lv_port_disp_init(void)
void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();
    /**
     * LVGL requires a buffer where it internally draws the widgets.
     * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
     * The buffer has to be greater than 1 display row
     *
     * There are 3 buffering configurations:
     * 1. Create ONE buffer:
     *      LVGL will draw the display's content here and writes it to your display
     *
     * 2. Create TWO buffer:
     *      LVGL will draw the display's content to a buffer and writes it your display.
     *      You should use DMA to write the buffer's content to the display.
     *      It will enable LVGL to draw the next part of the screen to the other buffer while
     *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
     *
     * 3. Double buffering
     *      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
     *      This way LVGL will always provide the whole rendered screen in `flush_cb`
     *      and you only need to change the frame buffer's address.
     */
    /* Example for 1) */
    // static lv_disp_draw_buf_t draw_buf_dsc_1;
    // static lv_color_t buf_1[MY_DISP_HOR_RES * 10];                          /*A buffer for 10 rows*/
    // lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/
    /* Example for 2) */
    static lv_disp_draw_buf_t draw_buf_dsc_2;
    static lv_color_t buf_2_1[DISP_BUF_SIZE];                        /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[DISP_BUF_SIZE];                        /*An other buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2,DISP_BUF_SIZE);   /*Initialize the display buffer*/

    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
    // static lv_disp_draw_buf_t draw_buf_dsc_3;
    // static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*A screen sized buffer*/
    // static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*Another screen sized buffer*/
    // lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
    //                       MY_DISP_VER_RES * LV_VER_RES_MAX);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LVGL
     *----------------------------------*/
    static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/
    /*Set up the functions to access to your display*/
    /*Set the resolution of the display*/
    disp_drv.hor_res = LV_HOR_RES_MAX;
    disp_drv.ver_res = LV_VER_RES_MAX;
    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_driver_flush;
    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_2;
    /*Required for Example 3)*/
    //disp_drv.full_refresh = 1;

    /* Fill a memory array with a color if you have GPU.
     * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
     * But if you have a different GPU you can use with this callback.*/
    //disp_drv.gpu_fill_cb = gpu_fill;

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}
3.添加lvgl_driver_init();
/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
    /*You code here*/
    lvgl_driver_init();
}

2.3.2 配置config

1.修改完后,就要配置lvgl的config
在这里插入图片描述

2.选择字体库
在这里插入图片描述
3.添加music的dome
在这里插入图片描述
4.使能spi的GPIO
在这里插入图片描述
在这里插入图片描述
配置好后保存,重新编译,下载后显示如下:
在这里插入图片描述

### 合宙 ESP32-C3 上移植 LVGL 图形库 #### 移植概述 LVGL 是一个轻量级的嵌入式图形界面库,支持多种硬件平台。对于合宙 ESP32-C3 平台而言,可以通过 Espressif 提供的相关组件和工具链完成 LVGL移植工作[^1]。 --- #### 硬件准备 ESP32-C3 支持 SPI 接口用于连接外部显示屏模块。推荐使用带有 ILI9341 或 ST7789 控制器的 TFT-LCD 屏幕作为显示设备。由于 ESP32-C3 内存有限,在开发过程中需特别注意优化内存占用[^2]。 --- #### 软件环境配置 以下是基于 Espressif IDF (Espressif IoT Development Framework) 进行 LVGL 移植所需的软件环境: 1. **安装 ESP-IDF 工具链** 下载并设置最新版本的 ESP-IDF 及其依赖项。具体操作可参考官方文档。 2. **引入 LVGL 组件** 使用 `idf.py` 命令将 `espressif/esp_lvgl_port` 添加至项目中。该组件已封装好适配层以便于快速部署[^3]: ```bash idf.py add-dependency espressif/esp_lvgl_port@~v1.4.0 ``` 3. **启用 LVGL 配置选项** 在项目的 Kconfig 文件中开启 LVGL 相关功能开关,并调整屏幕分辨率参数以匹配实际使用的显示器尺寸。 --- #### 示例代码 下面提供了一个简单的初始化流程以及绘制矩形框的例子: ```c #include "lvgl/lvgl.h" #include "driver/spi_master.h" void lvgl_init(void){ // 初始化SPI总线 spi_bus_config_t buscfg = { .mosi_io_num=GPIO_NUM_1, .miso_io_num=-1, .sclk_io_num=GPIO_NUM_2}; spi_device_interface_config_t devcfg={ .command_bits=8, .address_bits=8, .dummy_bits=0, .mode=0, .duty_cycle_pos=128, .cs_ena_pretrans=1, .cs_ena_posttrans=1}; spi_bus_initialize(VSPI_HOST,&buscfg,NULL); spi_bus_add_device(VSPI_HOST,&devcfg); /* Initialize the display buffer */ static lv_disp_draw_buf_t disp_buf; static lv_color_t buf[LV_HOR_RES_MAX * 10]; lv_disp_draw_buf_init(&disp_buf,buf,NULL,LV_HOR_RES_MAX*10); /* Register a display driver to LVGL*/ static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.flush_cb=my_display_flush; // 替换为您的刷新回调函数 disp_drv.draw_buf=&disp_buf; lv_disp_drv_register(&disp_drv); } // 主循环处理事件队列 void app_main(){ lvgl_init(); while(1){ lv_task_handler(); vTaskDelay(pdMS_TO_TICKS(5)); } } ``` 上述代码片段展示了如何启动 LVGL 库并与特定硬件交互。 --- #### 性能优化技巧 鉴于 ESP32-C3 较低的 SRAM 容量,可以采取如下措施提升性能表现: - 利用 `esp_mmap_assets` 将静态图像资源存储在外设 Flash 中而非加载到 RAM; - 减少动画帧率或禁用不必要的视觉特效; - 如果可能的话升级目标板子型号选用具备更大容量内部随机访问存储单元的产品系列比如 RP2040 或者其他增强型微控制器家族成员。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值