文章目录
- 1 工程简介
- 2 工程实现
- 2.1 制作字库
- 2.2 为字库自作分区表
- 2.3 将字库移植到lvgl工程中
- 2.4 将字库myFont.bin烧录到分区表中
- 2.5 编写程序测试
- 3 存在问题
1 工程简介
该工程在《ESP32基础应用之LVGL基础》之上实现中文的显示。
参考文章
- 《ESP32 IDF LVGL8.0 flash 外部字库显示 中文显示》
2 工程实现
2.1 制作字库
使用软件LvglFontToolV0.4自作二进制字库文件。
- 在电脑(C:\Windows\Fonts)找到合适的字体,并复制到桌面
- 打开 LvglFontToolV0.4 软件
- 最后获得两个文件,并查看myFont.bin大小,好后续为字库分配分区表大小。
2.2 为字库自作分区表
分区表知识可参考乐鑫官网《API 指南 — 分区表》
-
在官方例程中复制一份自定义分区表到lvgl工程中
修改分区表中的内容后如下# Name, Type, SubType, Offset, Size, Flags # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, font, data, 0x40, , 2M, //type选择data;SubType自定义(大于0x3F);Size根据字库大小合理定义
-
在ESP32配置菜单中选择自定义分区表
2.3 将字库移植到lvgl工程中
-
将字库myFont.bin放置到lvgl工程目录下
2. 将 myFont.c 放到合适的位置(注意需要将myFont.c添加到CMakeLists.txt)
2.4 将字库myFont.bin烧录到分区表中
- 命令
esptool.py --chip esp32 --port COM4 --baud 115200 write_flash -z 0x110000 myFont.bin
注意:烧录位置0x110000 可以通过自定义分区表计算,也可以在串口打印数据中查看
2.5 编写程序测试
-
修改myFont.c以适配工程,
/* *--------------------------------------------------------------- * Lvgl Font Tool * * 注:使用unicode编码 * 注:本字体文件由Lvgl Font Tool V0.4 生成 * 作者:阿里(qq:617622104) *--------------------------------------------------------------- */ #include "main.h" #include "esp_partition.h" #include "lvgl/lvgl.h"![在这里插入图片描述](https://img-blog.csdnimg.cn/9882e48826b24e988d12e61d7ad04e21.png) #include "lvgl_helpers.h" #define TAG "myFont.c" 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 = 0x9fa0, .bpp = 2, };![在这里插入图片描述](https://img-blog.csdnimg.cn/83af052dcf9a43bf942052986a0a4715.png) static uint8_t __g_font_buf[144];//如bin文件存在SPI FLASH可使用此buff esp_partition_t* partition_res=NULL; static uint8_t *__user_font_getdata(int offset, int size){ //如字模保存在SPI FLASH, SPIFLASH_Read(__g_font_buf,offset,size); //如字模已加载到SDRAM,直接返回偏移地址即可如:return (uint8_t*)(sdram_fontddr+offset); static uint8_t first_in = 1; if(first_in==1) { partition_res=esp_partition_find_first(0x01,0x40,NULL);//这个函数第一个参数是我们分区表的第四行的,第二列的参数,第二个是第三列的值 first_in=0; if (partition_res == NULL) { ESP_LOGI(TAG,"Failed to open file for reading\n"); return NULL; }else{ ESP_LOGI(TAG,"Successfully open file for reading\n"); } } esp_err_t res=esp_partition_read(partition_res,offset,__g_font_buf,size);//读取数据 if(res!=ESP_OK) { ESP_LOGI(TAG,"Failed to reading\n"); } 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; } //FangSong_GB2312,,-1 //字模高度:18 //XBF字体,外部bin文件 lv_font_t myFont = { .get_glyph_bitmap = __user_font_get_bitmap, .get_glyph_dsc = __user_font_get_glyph_dsc, .line_height = 18, .base_line = 0, };
-
在屏幕中显示中文
#include "lvgl/lvgl.h" #include "lvgl_helpers.h" #include "esp_partition.h" LV_FONT_DECLARE(myFont);//引入字库 static lv_obj_t * tv; static lv_style_t style_title; void fun(void) { tv = lv_tabview_create(lv_scr_act(), NULL); //以屏幕为父控件创建选项卡 lv_obj_t * label = lv_label_create(tv, NULL); lv_style_init(&style_title); lv_style_set_text_font(&style_title, LV_STATE_DEFAULT, &myFont); lv_obj_add_style(label, LV_LABEL_PART_MAIN, &style_title); lv_obj_set_pos(label, 100,100); lv_label_set_text(label ,"你好世界2022-12-17"); }
3 存在问题
- 文件之间的依赖行,即找不到所需的文件,这里要研究CMakeLists.txt文件
- 显示中文会很慢。