使用 LVGL 读取外部 FLASH 中的图片并显示出来

前言

在项目中经常使用到LVGL,苦于芯片的内部空间太过于小,项目中用到屏幕加载的图片就特别占空间,内部空间不够用的话只能使用外部FLASH存储图片(字库,以往有发过教程),以下是来源于其他博主的解释 原文链接

一般将图片数据存储到外部 Nor Flash 的常用方法包含(但不限于)以下几种(这里讨论的均为 bitmap 位图):
① 将图片数据转为 C 数组添加到代码中,在代码的链接文件中分配 RO 数组存储范围为外部 Flash。
优:该方法操作简单方便,图片数据随代码一起烧录,可直接调用图片数据
缺:需要对应外部 Flash 的烧录算法,每次下载 MCU 代码时会重复烧录图片数据,特别是图片较多时会导致每次下载代码很慢
② 将图片数据转为 .bin 文件并以文件形式存储在外部 Flash 的文件系统中。
优:图片管理清晰明了,方便增删改查,下载 MCU 代码时,无需重复写入图片数据
缺:需要添加文件系统,文件数据需先读取到 ram 中转再调用
③ 将图片数据转为 .bin 文件,并将 .bin 单独烧录到外部
优:无需外部 Flash 对应下载算法,可直接调用图片数据,下载 MCU 代码时,无需重复烧录图片数据
缺:通过地址调用图片数据,需要在代码中记下各图片数据起始地址
本次我们研究下第三种方法 将图片数据转为 .bin 文件,并将 .bin 单独烧录到外部

使用教程

一、将图片借助LVGL 官方转换工具 转换成对应的.bin文件 和 C文件

LVGL转换工具
1、选则合适的颜色的是 图中选的是带透明通道的颜色格式
2、选择要转换输出的格式 Binary RGB565 看屏幕的颜色格式 我这里的屏幕是RGB565
3、多转换一个C语言的格式 之后要用到

二、将bin文件烧录进FLASH中

	用各自的方法 合并bin文件 并烧录进去就好了 自行百度一下~

三、将转换出来的C文件提取出使用到的数据

C文件数据
把 const 去掉 然后复制到你的文件中去使用 最后的.data记得屏蔽掉,lv_img_dsc_t 如果要自己定义也可以~

typedef struct
{
  uint8_t *data; 	 // 用于存储从FLASH读取的图片数据
} FlashImageData;

贴图 图片数据相关描述属性
在这里插入图片描述

四、填好图片数据在FLASH的偏移地址 (记得加上0x04)

在自己写好的SPI_READ()函数中 添加上图片的地址偏移 + 0x04(头数据偏移)

// 读取图片数据到内存  第一个参数是偏移  看个人的读取函数参数位置即可 
   read_flash_image(0x4013d0 + 0x04, &flash_image.data, w.data_size);

五、示例代码

FlashImageData flash_image;

lv_img_dsc_t w = {
    .header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
    .header.always_zero = 0,
    .header.reserved = 0,
    .header.w = 62,
    .header.h = 62,
    .data_size = 3844 * LV_IMG_PX_SIZE_ALPHA_BYTE,
    //   .data = w_map,
};
// 根据图片在FLASH中的存储格式和地址等信息,读取图片数据到内存
void read_flash_image(const uint32_t image_start_address, uint8_t **data, const uint32_t image_size)
{
    *data = (uint8_t *)OS_Malloc(image_size);
    if (*data == NULL)
    {
        // 处理内存分配失败的情况
        LOG(LOG_LVL_INFO, "Memory allocation failed for image data!\n");
        return;
    }
    LOG(LOG_LVL_INFO, "%d %d \n", image_start_address, image_size);
    // 使用底层FLASH读取函数获取图片数据
    spi_flash_read_flash(image_start_address, *data, image_size);
}
void flash_image_test(void)
{
    lv_obj_t *Screen = lv_obj_create(NULL);                       // 创建一个屏幕对象
    lv_obj_set_size(Screen, LV_HOR_RES, LV_VER_RES);              // 设置屏幕大小
    lv_obj_set_style_bg_color(Screen, lv_color_hex(0x000000), 0); // 设置背景色

    lv_obj_t *label = lv_label_create(Screen); // 创建一个标签对象
    lv_label_set_text(label, "Hello, world!");
    lv_obj_align(label, LV_ALIGN_CENTER, 0, -60);
    lv_obj_set_style_text_color(label, lv_color_hex(0xffffff), 0);
  
    // 创建LVGL图像对象
    lv_obj_t *image_obj = lv_img_create(Screen);
    // 读取图片数据到内存
    read_flash_image(0x4013d0 + 0x04, &flash_image.data, w.data_size);
    // 设置图像对象的数据源为从FLASH读取的数据
    w.data = flash_image.data;
    lv_img_set_src(image_obj, &w);

    lv_obj_align(image_obj, LV_ALIGN_TOP_RIGHT, 0, 0);  //调节位置
    // 释放内存
 
    OS_Free(flash_image.data);

    lv_scr_load(Screen);
 }

六、实际效果

我多添加了一些图片显示,效果如下

实际效果

总结

在网上多翻阅一下其他博主的文章结合官方文档,总会有方法解决问题的!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐