金牌会员
- 积分
- 2285
- 金钱
- 2285
- 注册时间
- 2017-8-24
- 在线时间
- 375 小时
|
本帖最后由 xcc521 于 2020-8-3 08:39 编辑
1.内部字体添加方法,限制于FLASH的大小,所以只能放少许的字体,当然对于H7外扩SPI FLASH运行程序例外
LVGL FontTool V0.3,选择适当的字体
另存为.c复制到LVGL工程文件夹,必要时添加路径
lvgl.h处添加用户字体声明
除非你重新设置主题的字体选项,不然就在这里改变默认的字体
使用方法如下:
- static void slider_event_cb(lv_obj_t * obj, lv_event_t event)
- {
- char buf[32];
- if(obj == slider_speed_set)
- {
- if(event == LV_EVENT_VALUE_CHANGED)
- {
- Speed_Set = lv_slider_get_value(obj);
- sprintf(buf,"设定速度:%4d",Speed_Set);
- lv_label_set_text(label_speed_set,buf);
- }
- }
- }
复制代码
必须保证程序是UTF-8编码
2.外部字体设置方法,例如SPI FLASH
同样的方法,添加所有文字或者常用,生成外部bin文件和.c文件
bin文件拷贝到外置SD卡的SYSTEM/LVGLFONT文件夹
fontupd.c文件增加字体路径声明
- /* 字库存放在磁盘中的路径 */
- const char * GBK24_PATH="/SYSTEM/FONT/GBK24.FON"; /* GBK24的存放位置 */
- const char * GBK16_PATH="/SYSTEM/FONT/GBK16.FON"; /* GBK16的存放位置 */
- const char * GBK12_PATH="/SYSTEM/FONT/GBK12.FON"; /* GBK12的存放位置 */
- const char * UNIGBK_PATH="/SYSTEM/FONT/UNIGBK.BIN"; /* UNIGBK.BIN的存放位置 */
- const char * LVGL_12_PATH="/SYSTEM/LVGLFONT/myFont12.bin"; /* UNIGBK.BIN的存放位置 1,014,611 字节 */
- const char * LVGL_18_PATH="/SYSTEM/LVGLFONT/myFont18.bin"; /* UNIGBK.BIN的存放位置 1,732,774 字节 */
- const char * LVGL_24_PATH="/SYSTEM/LVGLFONT/myFont24.bin"; /* UNIGBK.BIN的存放位置 2,814,026 字节 */
复制代码 字体信息结构体增加位置和大小成员变量
- __packed typedef struct
- {
- uint8_t fontok; /* 字库存在标志,0XAA,字库正常;其他,字库不存在 */
- uint32_t ugbkaddr; /* unigbk的地址 */
- uint32_t ugbksize; /* unigbk的大小 */
- uint32_t f12addr; /* gbk12地址 */
- uint32_t gbk12size; /* gbk12的大小 */
- uint32_t f16addr; /* gbk16地址 */
- uint32_t gbk16size; /* gbk16的大小 */
- uint32_t f24addr; /* gbk24地址 */
- uint32_t gkb24size; /* gbk24的大小 */
- uint32_t lvgl_12addr; /* gbk24地址 */
- uint32_t lvgl_12size; /* gbk24的大小 */
- uint32_t lvgl_18addr; /* gbk24地址 */
- uint32_t lvgl_18size; /* gbk24的大小 */
- uint32_t lvgl_24addr; /* gbk24地址 */
- uint32_t lvgl_24size; /* gbk24的大小 */
- } _font_info;
复制代码 然后是更新的过程,添加相应的步骤即可
完整程序如下
- /* 字库区域占用的总扇区数大小
- #define FONTSECSIZE 2560
- /* 字库存放起始地址 */
- #define FONTINFOADDR 1024*1024*6
- /* 用来保存字库基本信息,地址,大小等 */
- _font_info ftinfo;
- /* 字库存放在磁盘中的路径 */
- const char * GBK24_PATH="/SYSTEM/FONT/GBK24.FON"; /* GBK24的存放位置 */
- const char * GBK16_PATH="/SYSTEM/FONT/GBK16.FON"; /* GBK16的存放位置 */
- const char * GBK12_PATH="/SYSTEM/FONT/GBK12.FON"; /* GBK12的存放位置 */
- const char * UNIGBK_PATH="/SYSTEM/FONT/UNIGBK.BIN"; /* UNIGBK.BIN的存放位置 */
- const char * LVGL_12_PATH="/SYSTEM/LVGLFONT/myFont12.bin"; /* UNIGBK.BIN的存放位置 1,014,611 字节 */
- const char * LVGL_18_PATH="/SYSTEM/LVGLFONT/myFont18.bin"; /* UNIGBK.BIN的存放位置 1,732,774 字节 */
- const char * LVGL_24_PATH="/SYSTEM/LVGLFONT/myFont24.bin"; /* UNIGBK.BIN的存放位置 2,814,026 字节 */
- /**
- * @brief 显示当前字体更新进度
- * @param x, y : 坐标
- * @param size : 字体大小
- * @param totsize : 整个文件大小
- * @param pos : 当前文件指针位置
- * @param color : 字体颜色
- * @retval 无
- */
- uint32_t fupd_prog(uint16_t x,uint16_t y,uint8_t size,uint32_t fsize,uint32_t pos)
- {
- float prog;
- uint8_t t=0XFF;
- prog=(float)pos/fsize;
- prog*=100;
- if(t!=prog)
- {
- lcd_show_string(x+3*size/2,y,240,320,size,"%",g_point_color);
- t=prog;
- if(t>100)t=100;
- lcd_show_num(x,y,t,3,size,g_point_color);/* 显示数值 */
- }
- return 0;
- }
- /**
- * @brief 更新某一个字库
- * @param x, y : 提示信息的显示地址
- * @param size : 提示信息字体大小
- * @param fpath : 字体路径
- * @param fx : 更新的内容
- * @arg 0, ungbk;
- * @Arg 1, gbk12;
- * @arg 2, gbk16;
- * @arg 3, gbk24;
- * @arg 4, gbk32;
- * @param color : 字体颜色
- * @retval 0, 成功; 其他, 错误代码;
- */
- uint8_t updata_fontx(uint16_t x,uint16_t y,uint8_t size,char *fxpath,uint8_t fx)
- {
- uint32_t flashaddr=0;
- FIL * fftemp;
- uint8_t *tempbuf;
- uint8_t res;
- uint16_t bread;
- uint32_t offx=0;
- uint8_t rval=0;
- fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); /* 分配内存 */
- if(fftemp==NULL)rval=1;
- tempbuf=mymalloc(SRAMIN,4096); /* 分配4096个字节空间 */
- if(tempbuf==NULL)rval=1;
- res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ);
- if(res)rval=2;/* 打开文件失败 */
- if(rval==0)
- {
- switch(fx)
- {
- case 0: /* 更新UNIGBK.BIN */
- ftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo); /* 信息头之后,紧跟UNIGBK转换码表 */
- ftinfo.ugbksize=fftemp->fsize; /* UNIGBK大小 */
- flashaddr=ftinfo.ugbkaddr;
- break;
- case 1:
- ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize; /* UNIGBK之后,紧跟GBK12字库 */
- ftinfo.gbk12size=fftemp->fsize; /* GBK12字库大小 */
- flashaddr=ftinfo.f12addr; /* GBK12的起始地址 */
- break;
- case 2:
- ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size; /* GBK12之后,紧跟GBK16字库 */
- ftinfo.gbk16size=fftemp->fsize; /* GBK16字库大小 */
- flashaddr=ftinfo.f16addr; /* GBK16的起始地址 */
- break;
- case 3:
- ftinfo.f24addr=ftinfo.f16addr+ftinfo.gbk16size; /* GBK16之后,紧跟GBK24字库 */
- ftinfo.gkb24size=fftemp->fsize; /* GBK24字库大小 */
- flashaddr=ftinfo.f24addr; /* GBK24的起始地址 */
- break;
- case 4:
- ftinfo.lvgl_12addr=ftinfo.f24addr+ftinfo.gkb24size;
- ftinfo.lvgl_12size=fftemp->fsize;
- flashaddr=ftinfo.lvgl_12addr;
- break;
- case 5:
- ftinfo.lvgl_18addr=ftinfo.lvgl_12addr+ftinfo.lvgl_12size;
- ftinfo.lvgl_18size=fftemp->fsize;
- flashaddr=ftinfo.lvgl_18addr;
- break;
- case 6:
- ftinfo.lvgl_24addr=ftinfo.lvgl_18addr+ftinfo.lvgl_18size;
- ftinfo.lvgl_24size=fftemp->fsize;
- flashaddr=ftinfo.lvgl_24addr;
- break;
- }
- while(res==FR_OK)/* 循环执行 */
- {
- res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); /* 读取数据 */
- if(res!=FR_OK)break; /* 执行错误 */
- w25qxx_write(tempbuf,offx+flashaddr,4096); /* 从0开始写入4096个数据 */
- offx+=bread;
- fupd_prog(x,y,size,fftemp->fsize,offx); /* 进度显示 */
- if(bread!=4096)break; /* 读完了 */
- }
- f_close(fftemp);
- }
- myfree(SRAMIN,fftemp); /* 释放内存 */
- myfree(SRAMIN,tempbuf); /* 释放内存 */
- return res;
- }
- /**
- * @brief 更新字体文件
- * @note 所有字库一起更新(UNIGBK,GBK12,GBK16,GBK24,GBK32)
- * @param x, y : 提示信息的显示地址
- * @param size : 提示信息字体大小
- * @param src : 字库来源磁盘
- * @arg "0:", SD卡;
- * @Arg "1:", FLASH盘
- * @arg "2:", U盘
- * @param color : 字体颜色
- * @retval 0, 成功; 其他, 错误代码;
- */
- uint8_t update_font(uint16_t x,uint16_t y,uint8_t size,char *src)
- {
- char *pname;
- uint32_t *buf;
- uint8_t res=0;
- uint16_t i,j;
- FIL *fftemp;
- uint8_t rval=0;
- res=0XFF;
- ftinfo.fontok=0XFF;
- pname=mymalloc(SRAMIN,100); /* 申请100字节内存 */
- buf=mymalloc(SRAMIN,4096); /* 申请4K字节内存 */
- fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); /* 分配内存 */
- if(buf==NULL||pname==NULL||fftemp==NULL)
- {
- myfree(SRAMIN,fftemp);
- myfree(SRAMIN,pname);
- myfree(SRAMIN,buf);
- return 5; /* 内存申请失败 */
- }
- /* 先查找文件是否正常 */
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)UNIGBK_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<4;/* 打开文件失败 */
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)GBK12_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<5;/* 打开文件失败 */
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)GBK16_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<6;/* 打开文件失败 */
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)GBK24_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<7;/* 打开文件失败 */
-
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)LVGL_12_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<1;/* 打开文件失败 */
-
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)LVGL_18_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<2;/* 打开文件失败 */
-
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)LVGL_24_PATH);
- res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
- if(res)rval|=1<<3;/* 打开文件失败 */
-
- myfree(SRAMIN,fftemp);/* 释放内存 */
- if(rval==0)/* 字库文件都存在 */
- {
- lcd_show_string(x,y,240,320,size,"Erasing sectors... ",g_point_color);/* 提示正在擦除扇区 */
- for(i=0; i<FONTSECSIZE; i++) /* 先擦除字库区域,提高写入速度 */
- {
- fupd_prog(x+20*size/2,y,size,FONTSECSIZE,i);/* 进度显示 */
- w25qxx_read((uint8_t*)buf,((FONTINFOADDR/4096)+i)*4096,4096);/* 读出整个扇区的内容 */
- for(j=0; j<1024; j++) /* 校验数据 */
- {
- if(buf[j]!=0XFFFFFFFF)break;/* 需要擦除 */
- }
- if(j!=1024)w25qxx_eraser_sector((FONTINFOADDR/4096)+i); /* 需要擦除的扇区 */
- }
- myfree(SRAMIN,buf);
- lcd_show_string(x,y,240,320,size,"Updating UNIGBK.BIN",g_point_color);
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)UNIGBK_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,0); /* 更新UNIGBK.BIN */
- if(res) {
- myfree(SRAMIN,pname);
- return 1;
- }
- lcd_show_string(x,y,240,320,size,"Updating GBK12.BIN ",g_point_color);
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)GBK12_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,1); /* 更新GBK12.FON */
- if(res) {
- myfree(SRAMIN,pname);
- return 2;
- }
- lcd_show_string(x,y,240,320,size,"Updating GBK16.BIN ",g_point_color);
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)GBK16_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,2); /* 更新GBK16.FON */
- if(res) {
- myfree(SRAMIN,pname);
- return 3;
- }
- lcd_show_string(x,y,240,320,size,"Updating GBK24.BIN ",g_point_color);
- strcpy((char*)pname,(char*)src); /* copy src内容到pname */
- strcat((char*)pname,(char*)GBK24_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,3); /* 更新GBK24.FON */
- if(res) {
- myfree(SRAMIN,pname);
- return 4;
- }
-
- lcd_show_string(x,y,240,320,size,"Updating LVGL12.BIN ",g_point_color);
- strcpy((char*)pname,(char*)src);
- strcat((char*)pname,(char*)LVGL_12_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,4);
- if(res) {
- myfree(SRAMIN,pname);
- return 5;
- }
- lcd_show_string(x,y,240,320,size,"Updating LVGL18.BIN ",g_point_color);
- strcpy((char*)pname,(char*)src);
- strcat((char*)pname,(char*)LVGL_18_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,5);
- if(res) {
- myfree(SRAMIN,pname);
- return 5;
- }
- lcd_show_string(x,y,240,320,size,"Updating LVGL24.BIN ",g_point_color);
- strcpy((char*)pname,(char*)src);
- strcat((char*)pname,(char*)LVGL_24_PATH);
- res=updata_fontx(x+20*size/2,y,size,pname,6);
- if(res) {
- myfree(SRAMIN,pname);
- return 5;
- }
-
-
- /* 全部更新好了 */
- ftinfo.fontok=0XAA;
- w25qxx_write((uint8_t*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); /* 保存字库信息 */
- }
- myfree(SRAMIN,pname);/* 释放内存 */
- myfree(SRAMIN,buf);
- return rval;/* 无错误 */
- }
- /**
- * @brief 初始化字体
- * @param 无
- * @retval 0, 字库完好; 其他, 字库丢失;
- */
- uint8_t font_init(void)
- {
- uint8_t t=0;
- w25qxx_init();
- while(t<10)/* 连续读取10次,都是错误,说明确实是有问题,得更新字库了 */
- {
- t++;
- w25qxx_read((uint8_t*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));/* 读出ftinfo结构体数据 */
- if(ftinfo.fontok==0XAA)break;
- delay_ms(20);
- }
- if(ftinfo.fontok!=0XAA)return 1;
- return 0;
- }
复制代码
生成的.c文件同样的步骤加到工程并添加声明
修改生成的字体驱动文件
添加路径和SPI读取信息
- #include "lvgl/lvgl.h"
- #include "BSP/NORFLASH/w25qxx.h"
- #include "TEXT/fontupd.h"</font>
- 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_y;
- }glyph_dsc_t;
- static x_header_t __g_xbf_hd = {
- .min = 0,
- .max = 0,
- .bpp = 0,
- };
- static uint8_t __g_font_buf[48];//如bin文件存在SPI FLASH可使用此buff
- 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);
- w25qxx_read(__g_font_buf,ftinfo.lvgl_12addr+offset,size);</font>
- return __g_font_buf;
- }
- static const uint8_t * __user_font_get_bitmap(const lv_font_t * font, uint32_t unicode_letter) {
- if( __g_xbf_hd.max==0 ) {
- uint8_t *p = __user_font_getdata(0, sizeof(x_header_t));
- memcpy(&__g_xbf_hd, p, sizeof(x_header_t));
- }
- 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( __g_xbf_hd.max==0 ) {
- uint8_t *p = __user_font_getdata(0, sizeof(x_header_t));
- memcpy(&__g_xbf_hd, p, sizeof(x_header_t));
- }
- 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 = 0;
- dsc_out->ofs_y = gdsc->ofs_y;
- dsc_out->bpp = __g_xbf_hd.bpp;
- return true;
- }
- return false;
- }
- //宋体,常规,12
- //字模高度:16
- //XBF字体,外部bin文件
- lv_font_t myFont12 = {
- .get_glyph_bitmap = __user_font_get_bitmap,
- .get_glyph_dsc = __user_font_get_glyph_dsc,
- .line_height = 16,
- .base_line = 0,
- };
复制代码 同样的方法改变主题的默认字体
- #define LV_THEME_DEFAULT_INCLUDE <stdint.h> /*Include a header for the init. function*/
- #define LV_THEME_DEFAULT_INIT lv_theme_material_init
- #define LV_THEME_DEFAULT_COLOR_PRIMARY LV_COLOR_RED
- #define LV_THEME_DEFAULT_COLOR_SECONDARY LV_COLOR_BLUE
- #define LV_THEME_DEFAULT_FLAG LV_THEME_MATERIAL_FLAG_LIGHT
- #define LV_THEME_DEFAULT_FONT_SMALL <font color="#ff8c00">&myFont12</font>
- #define LV_THEME_DEFAULT_FONT_NORMAL <font color="#ff8c00">&myFont12</font>
- #define LV_THEME_DEFAULT_FONT_SUBTITLE <font color="#ff8c00">&myFont18</font>
- #define LV_THEME_DEFAULT_FONT_TITLE <font color="#ff8c00">&myFont24</font>
复制代码
调用的方法也是一样,直接UTF-8写入中文即可
最新的字体生成器和上述SPI字体文件如下
|
|