LVGL V8.3:基于Arduino的使用lvgl文件系统读取SD卡内容

编译平台介绍

  • Windows10
  • Vscode+PlatformIO
  • 使用ESP-WROOM-32模块
  • 包含GC9A01驱动的240*240屏幕一块
  • 包含SPI驱动的Flash卡
  • lvgl版本8.3.2
  • 移植前的准备

    使用tft-eSPI解决屏幕驱动

    移植tft-eSPI 请参考其它文章,难度不大,这里不在介绍

    移植LVGL

    移植LVGL 请参考其它文章,这里不再介绍,运行lvgl自带demos或者examples配置比较麻烦,能写一个简单的控件并正确显示就可以了,不用非纠结显示自带的案例

    把SD卡格式化为FAT32格式

    SD卡插入电脑格式化为fat32格式

    解决引脚冲突

    TFlash卡与屏幕驱动均使用SPI驱动,不修改默认引脚会造成引脚冲突,esp32用户一般使用两组spi,分别是HSPIVSPI,引脚序号如下:

    SPI引脚图

    我的屏幕引脚分配方案如下,修改User_Setup.h文件,屏幕驱动使用HSPI相关引脚:

    // For ESP32 Dev board (only tested with GC9A01 display)
    // The hardware SPI can be mapped to any pins
    
    #define TFT_MOSI 13 // In some display driver board, it might be written as "SDA" and so on.
    #define TFT_SCLK 14
    #define TFT_CS   15  // Chip select control pin
    #define TFT_DC   27  // Data Command control pin
    #define TFT_RST  33  // Reset pin (could connect to Arduino RESET pin)
    #define TFT_BL   22  // LED back-light
    

    这样SD卡驱动自然是使用VSPI,默认就是不用做任何修改,系统默认使用SDMMC方式驱动,使用SPI驱动的头文件没有包含在头文件路径中,在c_cpp_properties.json文件中添加头文件路径,否则报错:

     "includePath": [
     ···
    	"C:/Users/xx/.platformio/packages/framework-arduinoespressif32/libraries/SD/src",
    ···
    

    验证程序

    #include <Arduino.h>
    #include "SD.h"
    #include "FS.h"
    void test_SD(void)
    {
    	if(!SD.begin())
        {
            Serial.println("Card Mount Failed");
            return MY_FS_INIT_FAIL;
        }
        else
        {
            Serial.println("Card Mount Success");
        }
        uint8_t cardType = SD.cardType();
     
        if(cardType == CARD_NONE){
            Serial.println("No SD card attached");
            return MY_FS_INIT_FAIL;
        }
        Serial.print("SD Card Type: ");
        if(cardType == CARD_MMC){
            Serial.println("MMC");
        } else if(cardType == CARD_SD){
            Serial.println("SDSC");
        } else if(cardType == CARD_SDHC){
            Serial.println("SDHC");
        } else {
            Serial.println("UNKNOWN");
        }
    }
    

    测试函数结果如下:

    Card Mount Success
    SD Card Type: SDSC
    

    开始移植

    lv_config.h配置

    打开文件系统宏 使用FATFS,并分配盘符,我这里使用的是S,这里就移植好了

    /*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
    #define LV_USE_FS_FATFS 1
    #if LV_USE_FS_FATFS
        #define LV_FS_FATFS_LETTER 'S'     /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
        #define LV_FS_FATFS_CACHE_SIZE 0    /*>0 to cache this number of bytes in lv_fs_read()*/
    #endif
    

    修改DIR为FF_DIR

    lv_fs_fatfs.c文件中的DIR替换为FF_DIR,应该有两处,否则会报错

    /**
     * Initialize a 'fs_read_dir_t' variable for directory reading
     * @param drv pointer to a driver where this function belongs
     * @param dir_p pointer to a 'fs_read_dir_t' variable
     * @param path path to a directory
     * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
     */
    static void * fs_dir_open (lv_fs_drv_t * drv, const char *path)
    {
        FF_DIR * d = lv_mem_alloc(sizeof(FF_DIR));
        if(d == NULL) return NULL;
     
        FRESULT res = f_opendir(d, path);
        if(res != FR_OK) {
            lv_mem_free(d);
            d = NULL;
        }
        return d;
    }
    

    lv_fs的使用

    使用前初始化,按标准来讲应将SD初始化部分放入lv_fs_fatfs.c文件的fs_init函数中,但是在C++环境下,经常报一些语言相关错误,属于c与C++混编。简单的解决方法是把SD卡初始化放在lv文件系统初始化之前就可以了,在SD卡中放入一个Hello World!!的测试文件测试函数如下:

    #include <lvgl.h>
    #include "SD.h"
    #include "my_fs_drv.h"
    //自己包装的文件系统初始化函数
    int my_fs_drv_init(void)
    {
        if(!SD.begin())
        {
            Serial.println("Card Mount Failed");
            return MY_FS_INIT_FAIL;
        }
        else
        {
            Serial.println("Card Mount Success");
        }
        uint8_t cardType = SD.cardType();
     
        if(cardType == CARD_NONE){
            Serial.println("No SD card attached");
            return MY_FS_INIT_FAIL;
        }
        Serial.print("SD Card Type: ");
        if(cardType == CARD_MMC){
            Serial.println("MMC");
        } else if(cardType == CARD_SD){
            Serial.println("SDSC");
        } else if(cardType == CARD_SDHC){
            Serial.println("SDHC");
        } else {
            Serial.println("UNKNOWN");
        }
        lv_fs_fatfs_init();  //lvgl 文件系统初始化 放在SD卡初始化之后就行
    }
    //测试读取函数
    void lv_fs_test(void)
    {
    	lv_fs_file_t f;
    	lv_fs_res_t res;
    	res = lv_fs_open(&f, "S:folder/file.txt", LV_FS_MODE_RD);
    	if(res != LV_FS_RES_OK) 
    	{
    		Serial.println("Open fail");
    		
    	}
    	else
    	{
    		Serial.println("Open OK");
    		uint32_t read_num;
    		uint8_t buf[8];
    		res = lv_fs_read(&f, buf, 8, &read_num);
    		Serial.printf("read:%s",buf);
    		lv_fs_close(&f);
    	}
    	
    		
    	
    }
    

    执行测试后程序打印如下:

    Open OK
    read:Hello Wo
    

    至此移植完毕

    物联沃分享整理
    物联沃-IOTWORD物联网 » LVGL V8.3:基于Arduino的使用lvgl文件系统读取SD卡内容

    发表评论