ESP32在ESP-IDF框架下为LVGL(v8.3)配置SD卡文件系统

踩坑记录

1、如果SD卡曾经做过系统盘(比如说:作为树莓派的系统盘),那么要把系统盘的分区合并成一个(这个网上有很多教程),并重新格式化,否则实验会失败。
2、并不是买回来的新的SD卡就一定能用(并不是说用读卡器插在电脑上能够正常读写,就表示一定能够实验成功),买过几张卡,确实有不能用的,导致改bug搞了一下午没有成功。
3、可以先运行一下IDF提供的SD卡示例,判断是否能够挂载文件系统成功(如果能够正常读取卡信息就表示成功了)。
说明:实验没有采用lv_fs_if作为一个组件的移植方式,可能与网上的资料稍有不同。

移植过程

说明:本实验是在该实验点击这里的基础上进行的。
1、打开小齿轮(SDK Configureation editor)找到3rd Party Libraries,选中File sysytem on top of FatFS,修改下面为83(ASCII中的‘S’),下面是读取使用的缓冲区大小。
在这里插入图片描述
2、创建新的小组件(ctrl+shift+p ESP-IDF:创建新的ESP-IDF组件命名为sd_card(可自行更改)),在include文件夹中自动创建lesd_card.h文件,include文件夹之外自动创建了sd_card.cCMakeLists.txt文件。此外将示例项目sdspi中的Kconfig.projbuild拷贝过来。四个文件的内容如下。(sd_card组件代码内容是由sd卡示例文件sdspi示例项目修改而来,只需要添加一句host.slot = SPI3_HOST即可,因为SPI2_HOST已经被屏幕占用了,可直接使用下面文件,也可以自己去更改。)编译一下项目,建议先使用小齿轮(menuconfig)中的默认引脚(引脚号会根据设备有相关的默认值)。

//*************************************sd_card.h文件内容******************************************
#ifndef _SD_CARD_H
#define _SD_CARD_H

#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "esp_err.h"

esp_err_t sd_init();

#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif


//************************************sd_card.c文件内容*******************************************
#include "sdcard.h"
#define MOUNT_POINT "/sdcard"
#define PIN_NUM_MISO  CONFIG_EXAMPLE_PIN_MISO
#define PIN_NUM_MOSI  CONFIG_EXAMPLE_PIN_MOSI
#define PIN_NUM_CLK   CONFIG_EXAMPLE_PIN_CLK
#define PIN_NUM_CS    CONFIG_EXAMPLE_PIN_CS
sdmmc_card_t *card;
esp_err_t sd_init()
{
    esp_err_t ret;
    static const char *TAG = "example";
    // Options for mounting the filesystem.
    // If format_if_mount_failed is set to true, SD card will be partitioned and
    // formatted in case when mounting fails.
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .format_if_mount_failed = true,
#else
        .format_if_mount_failed = false,
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .max_files = 5,
        .allocation_unit_size = 16 * 1024
    };
    sdmmc_card_t *card;
    const char mount_point[] = MOUNT_POINT;
    ESP_LOGI(TAG, "Initializing SD card");

    // Use settings defined above to initialize SD card and mount FAT filesystem.
    // Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
    // Please check its source code and implement error recovery when developing
    // production applications.
    ESP_LOGI(TAG, "Using SPI peripheral");

    sdmmc_host_t host = SDSPI_HOST_DEFAULT();
    host.slot = SPI3_HOST;
    spi_bus_config_t bus_cfg = {
        .mosi_io_num = PIN_NUM_MOSI,
        .miso_io_num = PIN_NUM_MISO,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };
    ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return;
    }

    // This initializes the slot without card detect (CD) and write protect (WP) signals.
    // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
    sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    slot_config.gpio_cs = PIN_NUM_CS;
    slot_config.host_id = host.slot;

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);

    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount filesystem. "
                     "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
        } else {
            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
                     "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
        }
        return;
    }
    ESP_LOGI(TAG, "Filesystem mounted");

    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);
    return ESP_OK;

}

//******************************CMakeLists.txt文件内容*******************************************
idf_component_register(
        SRCS	"sd_card.c"
        INCLUDE_DIRS "include"
        REQUIRES  fatfs)

#******************************Kconfig.projbuild文件内容*******************************************
menu "SD SPI Example Configuration"

    config EXAMPLE_FORMAT_IF_MOUNT_FAILED
        bool "Format the card if mount failed"
        default n
        help
            If this config item is set, format_if_mount_failed will be set to true and the card will be formatted if
            the mount has failed.

    config EXAMPLE_PIN_MOSI
        int "MOSI GPIO number"
        default 15 if IDF_TARGET_ESP32
        default 35 if IDF_TARGET_ESP32S2
        default 35 if IDF_TARGET_ESP32S3
        default 4  # C3 and others

    config EXAMPLE_PIN_MISO
        int "MISO GPIO number"
        default 2 if IDF_TARGET_ESP32
        default 37 if IDF_TARGET_ESP32S2
        default 37 if IDF_TARGET_ESP32S3
        default 6  # C3 and others

    config EXAMPLE_PIN_CLK
        int "CLK GPIO number"
        default 14 if IDF_TARGET_ESP32
        default 36 if IDF_TARGET_ESP32S2
        default 36 if IDF_TARGET_ESP32S3
        default 5  # C3 and others

    config EXAMPLE_PIN_CS
        int "CS GPIO number"
        default 13 if IDF_TARGET_ESP32
        default 34 if IDF_TARGET_ESP32S2
        default 34 if IDF_TARGET_ESP32S3
        default 1  # C3 and others

endmenu

3、SD卡接线方式,如果想节省一个引脚,可将CS引脚直接接地。接线方式与安信可esp-cam模组相同,原理图参考
在这里插入图片描述

ESP32引脚SD卡引脚
37MISO
35MOSI
36CLK
38CS

4、因为LVGL要使用文件系统和初始化SD卡,所以LVGL要依赖fatfs和sd_card组件。打开lvgl–>env_support–>cmake–>esp.cmake文件,在第45行位置添加依赖(REQUIRES后面的内容),添加后的依赖如下:

  idf_component_register(SRCS ${SOURCES} ${EXAMPLE_SOURCES} ${DEMO_SOURCES}
      INCLUDE_DIRS ${LVGL_ROOT_DIR} ${LVGL_ROOT_DIR}/src ${LVGL_ROOT_DIR}/../
                   ${LVGL_ROOT_DIR}/examples ${LVGL_ROOT_DIR}/demos
      REQUIRES esp_timer
      fatfs
      sd_card)

5、打开lv_fs_fatfs.c文件(路径:lvgl/src/extra/libs/fsdrv/),添加sd_card.h头文件(在第10行位置:#include "sd_card.h")。将第230行的两个DIR修改为FF_DIR。在第92行处fs_init(void)函数中调用sd_init()函数来初始化sd卡。
6、注:这种方式移植文件系统与使用lv_fs_if组件的方式不同,当调用lv_init()函数的时候,就已经初始化SD卡并且挂载了文件系统。所以对于上一次实验,不需要更改main.c的任何内容,就实现了初始化SD卡和文件系统。

测试

1、将上次实验的main.c直接拿过来。在lv_init()之后使用vTaskDelay(pdMS_TO_TICKS(5));延时5ms,然后在初始化屏幕驱动(lvgl_driver_init();),不然可能出现花屏
2、在阿里巴巴矢量图标库中随便下载一个200像素的小图片,并将图片在LVGL官网提供的图片转化工具Online Image Converter中生成二进制.bin文件。并将改文件存储到SD卡中pictures文件夹中。
在这里插入图片描述
3、使用SquareLine studio工具1.2.2版本,拖拽一个image控件放到屏幕中。像下面这样。将生成的文件放在my_ui组建中(上一实验最后有讲)。

在这里插入图片描述
4、在main.c的ui_init()函数之后,调用lv_img_set_src(ui_Image2,“S:pictures/xxx.bin”);其中xxx是图片的名字。运行结果如下,表明SD卡文件系统移植成功:

在这里插入图片描述

完整的主文件代码(main.c)如下:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_freertos_hooks.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "driver/gpio.h"
#include "lvgl/lvgl.h"
#include "lvgl_helpers.h"
#include <lv_demos.h>
#include <ui.h>


/*********************
 *      DEFINES
 *********************/
#define TAG "demo"
#define LV_TICK_PERIOD_MS 1

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void lv_tick_task(void *arg);
static void guiTask(void *pvParameter);


/**********************
 *   APPLICATION MAIN
 **********************/
void app_main() {
    xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
}

SemaphoreHandle_t xGuiSemaphore;

static void guiTask(void *pvParameter) {

    (void) pvParameter;
    xGuiSemaphore = xSemaphoreCreateMutex();
    lv_init();
    vTaskDelay(pdMS_TO_TICKS(5));
    lvgl_driver_init();
    lv_color_t* buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf1 != NULL);
    static lv_color_t *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);
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.flush_cb = disp_driver_flush;
    disp_drv.draw_buf = &disp_buf;
    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));
    /* 在这里更换自己的UI */
    ui_init();
    lv_img_set_src(ui_Image2,"S:pictures/cat.bin");
    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);
    vTaskDelete(NULL);
}

static void lv_tick_task(void *arg) {
    (void) arg;
    lv_tick_inc(LV_TICK_PERIOD_MS);
}

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
根据引用所述,使用Vscode或ESP-IDF CMD打开的设置和配置是一样的,两种方法都可以使用。 根据引用所述,在进行esp-idf配置lvgl时,需要做以下几个步骤: 1. 打开lv_fs_fatfs.c文件(路径:lvgl/src/extra/libs/fsdrv/)。 2. 在第10行的位置添加sd_card.h头文件(#include "sd_card.h")。 3. 将第230行的两个DIR修改为FF_DIR。 4. 在第92行处的fs_init(void)函数中调用sd_init()函数来初始化sd卡。 这样就完成了esp-idf配置lvgl的过程。请注意,使用这种方式移植文件系统与使用lv_fs_if组件的方式不同。在调用lv_init()函数时,已经初始化了SD卡并且挂载了文件系统。因此,不需要更改main.c的任何内容,就可以实现初始化SD卡文件系统。 如果出现错误,说明下载的lv_esp32_drivers仓库可能不是指定的仓库(不是master主分支仓库)。可以在线查看lv_esp32_drivers/lvgl_helpers.c的内容,确认是否符合要求。由于LVGL的目录结构变化,lvgl_helpers.c文件的内容也可能发生变化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ESP32_esp-idf_lvgl_V8环境搭建移植](https://blog.csdn.net/qq_43588817/article/details/126680595)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ESP32ESP-IDF框架下为LVGL(v8.3)配置SD卡文件系统](https://blog.csdn.net/weixin_42181820/article/details/130199337)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小魏先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值