当前位置: 首页 > news >正文

解决LVGL与FATFS编码格式冲突及外挂字库方案

问题描述

在使用LVGL和FATFS文件系统时,遇到了编码格式不一致的问题:

  • LVGL 默认使用 UTF-8 编码
  • CubeMX生成的FATFS 使用 GBK 编码
  • 从SD卡读取的字符文字为GBK格式,导致在LVGL中显示时出现乱码

stm-loc1.png

参考解决方案:http://www.openedv.com/forum.php?mod=viewthread&tid=348136&highlight=lvgl%2B%D6%D0%CE%C4

编码转换方案

转换逻辑

  • LVGL中文存入SD卡:UTF-8 → GBK
  • LVGL显示SD卡文字:GBK → UTF-8

实现步骤

  1. 下载转换文件
    GBK转UTF-8修改好的文件

  2. 导入工程
    将文件导入Keil工程

  3. 代码示例

#include "gbk2utf8.h"char name[] = "你好你好你好";
char utf8_text[64];
str_gbk2utf8(name, utf8_text);
lv_label_set_text_fmt(guider_ui.screen_text_name, "%s", utf8_text);

LVGL外挂字库方案

准备工作

使用 LvglFontTool 工具生成字库文件

操作步骤

1. 选择字体和大小

stm-loc2.png

2. 添加字符集

  • 点击"加入常用汉字"
  • 添加可能用到的生僻字和中文符号,避免显示为方框
    stm-loc3.png

3. 可选:添加Awesome图标

stm-loc4.png

4. 设置输出参数

  • 设置字体名称和尺寸
  • 类型选择"外部bin文件"
    stm-loc5.png

5. 生成文件

  • 点击"开始转换"

  • 生成两个文件:

    • .bin文件 → 拷贝到SD卡

      stm-loc6.png

    • .c文件 → 加入Keil工程
      stm-loc7.png

代码修改

修改 YaHeiFont12.c 文件:

/*
*---------------------------------------------------------------
*                        Lvgl Font Tool                         
*                                                               
* 注:使用unicode编码                                              
* 注:本字体文件由Lvgl Font Tool V0.4 生成                          
* 作者:阿里(qq:617622104)                                         
*---------------------------------------------------------------
*/#include "lvgl.h"
#include "fatfs.h"
#include "ff.h"
#include <stdio.h>typedef struct{uint16_t min;uint16_t max;uint8_t  bpp;uint8_t  reserved[3];
}x_header_t;typedef struct{uint32_t pos;
}x_table_t;typedef struct{uint8_t adv_w;uint8_t box_w;uint8_t box_h;int8_t  ofs_x;int8_t  ofs_y;uint8_t r;
}glyph_dsc_t;static x_header_t __g_xbf_hd = {.min = 0x0020,.max = 0xf244,.bpp = 1,
};static uint8_t __g_font_buf[63];  // 字体读取缓冲区static uint8_t *__user_font_getdata(int offset, int size){uint32_t br;// 注意修改SD卡中字库文件路径if( f_open(&SDFile, (const TCHAR*)"0:/Font/YaHeiFont12.bin", FA_READ) != FR_OK ) {printf("font.bin open failed\r\n");} else {if( f_lseek(&SDFile, (FSIZE_t)offset) != FR_OK ) {printf("font lseek failed\r\n");}if( f_read(&SDFile, __g_font_buf, (UINT)size, (UINT*)&br) != FR_OK ) {printf("font read failed\r\n");}f_close(&SDFile);}return __g_font_buf;
}static const uint8_t * __user_font_get_bitmap(const lv_font_t * font, uint32_t unicode_letter) {if( unicode_letter>__g_xbf_hd.max || unicode_letter<__g_xbf_hd.min ) {return NULL;}uint32_t unicode_offset = sizeof(x_header_t)+(unicode_letter-__g_xbf_hd.min)*4;uint32_t *p_pos = (uint32_t *)__user_font_getdata(unicode_offset, 4);if( p_pos[0] != 0 ) {uint32_t pos = p_pos[0];glyph_dsc_t * gdsc = (glyph_dsc_t*)__user_font_getdata(pos, sizeof(glyph_dsc_t));return __user_font_getdata(pos+sizeof(glyph_dsc_t), gdsc->box_w*gdsc->box_h*__g_xbf_hd.bpp/8);}return NULL;
}static bool __user_font_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) {if( unicode_letter>__g_xbf_hd.max || unicode_letter<__g_xbf_hd.min ) {return NULL;}uint32_t unicode_offset = sizeof(x_header_t)+(unicode_letter-__g_xbf_hd.min)*4;uint32_t *p_pos = (uint32_t *)__user_font_getdata(unicode_offset, 4);if( p_pos[0] != 0 ) {glyph_dsc_t * gdsc = (glyph_dsc_t*)__user_font_getdata(p_pos[0], sizeof(glyph_dsc_t));dsc_out->adv_w = gdsc->adv_w;dsc_out->box_h = gdsc->box_h;dsc_out->box_w = gdsc->box_w;dsc_out->ofs_x = gdsc->ofs_x;dsc_out->ofs_y = gdsc->ofs_y;dsc_out->bpp   = __g_xbf_hd.bpp;return true;}return false;
}// YaHei Consolas Hybrid,YaHei Consolas Hybrid Regular,12
// 字模高度:21
// XBF字体,外部bin文件
const lv_font_t YaHeiFont12 = {.get_glyph_bitmap = __user_font_get_bitmap,.get_glyph_dsc = __user_font_get_glyph_dsc,.line_height = 21,.base_line = 0,
};

配置LVGL

1. 在 lv_conf.h 中添加自定义字体

stm-loc8.png

2. 设置标签控件的字体

stm-loc9.png

最终效果

成功实现外挂字库显示中文:
stm-loc10.png

通过以上方案,完美解决了LVGL与FATFS编码格式冲突问题,并实现了灵活的外挂字库功能。

http://www.gsyq.cn/news/64427.html

相关文章:

  • GraphRAG进阶:基于Neo4j与LlamaIndex的DRIFT搜索实现详解
  • noip板子
  • Linux_Socket_浅谈UDP - 教程
  • Jetlinks 物联网平台 开源版学习源码分析
  • Tita CRM一体化平台:破解销售管理五大痛点,实现业绩可持续增长
  • NOIP 算法合集
  • 使用cnpm(中国镜像源的npm客户端)来安装electron
  • 2025年11月中国电动叉车销售公司推荐榜单:主流品牌综合对比分析
  • 详细介绍:Qt样式深度解析
  • 替代模型简化复杂物理仿真任务
  • NOIP day -1 笔记
  • 2025-11-28 用前端react的架构来类比 NestJS 的各个部分(deepseek)
  • 【Microsoft Learn】Microsoft Azure 服务 - 教程
  • Spring AI 代码分析(十)--Spring Boot集成
  • WSL 迁移发行版位置
  • 详细介绍:Web安全深度实战:从漏洞挖掘到安全防护
  • 敬请人(自己)采/警示后人(自己)合辑
  • 使用RecyclerView.ItemDecoration自定义RecyclerView圆角滚动条
  • 技术分析:越南部分银行 App 不当使用 iOS 私有 API
  • Windows Docker 安装 RabbitMQ(包含客户端图形界面) - Higurashi
  • 《R语言医学数据分析实战》学习记录|第三章 数据框的操作
  • 软件工程学习日志2025.11.28
  • 漏洞赏金猎人的深度侦察方法论 | 第一部分
  • 2025年11月晶振厂家推荐:权威榜单与选择指南
  • 2025年11月晶振厂家推荐榜单:知名品牌综合对比与选购指南
  • Day49(19)-F:\硕士阶段\Java\课程代码\后端\web-ai-code\web-ai-project02\tlias-web-management
  • 人工智能:用Gemini3一分钟生成手势控制3D粒子交互系统
  • 酶蛋白定向进化难题?泰克生物酵母展示服务,高效筛选“高活性酶”突变体
  • 上两个GPT写的锁,一个是文件锁,一个是Redis锁,写的那是相当的完美
  • 11月27号