教程不断更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429
第29章 emWin6.x的XBF格式全字库生成和使用方法(Unicode编码,SPI Flash方案)
本章节为大家讲解XBF格式全字库的生成和使用方法。XBF格式字库可以存储到任何外部存储介质中,带不带文件系统都没有关系,且XBF格式字体支持抗锯齿效果,显示大字体的时候效果非常棒。XBF格式字体也是用FontCvt生成的,编码为Unicode。本章节以SPI Flash为例给大家进行讲解(SPI Flash就是SPI接口的Flash存储芯片)。
29.1 初学者重要提示
29.2 下载算法存放位置(操作前必看)
29.3 XBF格式字体生成方法
29.4 不同XBF格式字体的合并方法
29.5 XBF格式字体使用方法
29.6 内部Flash和SPI Flash程序调试下载配置(重要必看)
29.7 实验例程说明(RTOS)
29.8 实验例程说明(裸机)
29.9 总结
29.1 初学者重要提示
1、 字体小工具需要使用此贴提供的,其它大部分是Demo版本:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=107218 。
2、 STM32H7驱动SPI Flash的MDK下载算法制作方法已经发布,详见第84章。
http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 。
3、 下载本章节相关例子前,务必先添加好SPI Flash的下载算法。本章使用的方法支持内部Flash和外部SPI Flash可以同时下载。如此以来,大家可以方便的将字库,图库和主题存到外部SPI Flash,简单易用,大大方便大家项目实战。
4、 本章节配套的例子是将XBF格式字库烧写到不带文件系统的SPI Flash里面进行测试,效果比较好,也比较流畅。实际项目切不可给SPI Flash加上文件系统后使用XBF格式字体,否则会比较卡顿。
5、 emWin官方提供的字体生成软件FontCvt不支持GB编码,所以只能使用FontCvt支持的Unicode编码。
6、 教程中让大家将要显示汉字的C文件转换为UTF-8编码,指的是将这个汉字所在的C文件转换为UTF-8编码,这点要切记,详情请看28.4小节的说明。
另外特别注意MDK5编译错误missing closing quote,解决办法看本章教程28章的第28.6.2小节。
7、 XBF格式所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数的位置
下图是英文版手册里面API函数的位置:
29.2 下载算法存放位置(操作前必看)
(注:例子下载地址 http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 )
编译例子:V7-065_SPI Flash的MDK下载算法制作,生成的算法文件位于此路径下:
生成算法文件后,需要大家将其存到到MDK安装目录,有两个位置可以存放,任选其一,推荐第2种:
- 第1种:存放到MDK的STM32H7软包安装目录里面:KeilSTM32H7xx_DFP2.6.0CMSISFlash(软包版本不同,数值2.6.0不同)。
- 第2种:MDK的安装目录 ARMFlash里面。
29.3 XBF格式字体生成方法
下面以生成16点阵,宋体为例来说明使用FontCvt生成XBF格式字体的方法。
1、 第1步:打开字体生成软件FontCvt,选择字体类型Standard,编码选择16bit Unicode。
点击OK后,弹出如下窗口:
再点击确定后弹出FontCvt界面变成如下效果:
2、 第2步:点击File->Save As
弹出如下窗口:
生成字体的过程中,左下角会有一个Unicode编码值从0x0000开始递增的过程,转换结束后显示Ready。
此时桌面就会生成XBF字库了。如果要生成的点阵字体比较大,此过程比较慢。本次转换生成的文件如下:
同样的方法再生成24点阵和32点阵的字体:
本章节配套的例子把这三种生成的字体都进行了测试。
29.4 不同XBF格式字体文件的合并方法
本小节讲解如何将上面小节生成的三种点阵字体合并成一个bin文件。合并成一个文件比较有实际意义,本章节配套的例子是将三种点阵字体都加载到SPI Flash里面,合并成一个bin文件后,加载一次就可以了。
1、 第1步:登陆网址http://www.armbbs.cn/forum.php?mod=viewthread&tid=8627 下载小软件--->文件合并助手。
2、 第2步:打开文件合并助手,加载本章29.2小节生成的三种字体
添加字库后,效果如下:
输出窗口已经自动生成了对应字体的首地址。这个地址要保存好,后面要用到。
3、 第3步:点击右下角的合并,会弹出一个窗口
点击保存后,桌面后生成一个font.bin的文件:
注意,合并后的这个文件不要超过8MB,因为本教程配套板子的SPI Flash大小是8MB。这个文件的实际大小大约是7.89MB,没有超过8MB。
29.5 XBF格式字体使用方法
XBF格式字体的使用通过下面五步就可以实现:
1、 第1步:定义16点阵,24点阵和32点阵的XBF格式字体
代码语言:javascript复制/* 宋体16点阵定义 */
#define XBF_Font16BaseAdd 0x00000000
GUI_XBF_DATA XBF_Data16;
GUI_FONT XBF_Font16;
void *Fontfile16;
/* 宋体24点阵定义 */
#define XBF_Font24BaseAdd 0x0015B7B6
GUI_XBF_DATA XBF_Data24;
GUI_FONT XBF_Font24;
void *Fontfile24;
/* 宋体32点阵定义 */
#define XBF_Font32BaseAdd 0x003CEF64
GUI_XBF_DATA XBF_Data32;
GUI_FONT XBF_Font32;
void *Fontfile32;
每个字体都是三个变量和一个宏定义,宏定义用来设置字体的首地址,也就是29.3小节时给大家强调的。
另外三个变量的定义是创建XBF格式字体必须的,变量名可以任意定义,但是这三个变量不能少。其中指针类型变量 void *Fontfile16,void *Fontfile24和void *Fontfile32都没有用到,如果使用了文件系统就用到了,这三个变量是用来定义文件系统变量的,比如使用FatFS文件系统,这三个变量就应该修改为FIL Fontfile16,FIL Fontfile24和FIL Fontfile32。
2、 第2步:创建16点阵,24点阵和32点阵的XBF格式字体
代码语言:javascript复制/*
*********************************************************************************************************
* 函 数 名: _cbGetData16
* 功能说明: XBF字体的回调函数, 16点阵
* 形 参: Off - 地址偏移
* NumBytes - 需要读出的字节数
* pVoid - 指针变量,一般用于带文件系统时的FIL类型变量
* pBuffer - 获取字体的点阵数据
* 返 回 值: 0 表示成功 1 表示失败
*********************************************************************************************************
*/
static int _cbGetData16(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
{
/* 读取点阵数据 */
sf_ReadBuffer(pBuffer, XBF_Font16BaseAdd Off, NumBytes);
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: _cbGetData24
* 功能说明: XBF字体的回调函数, 24点阵
* 形 参: Off - 地址偏移
* NumBytes - 需要读出的字节数
* pVoid - 指针变量,一般用于带文件系统时的FIL类型变量
* pBuffer - 获取字体的点阵数据
* 返 回 值: 0 表示成功 1 表示失败
*********************************************************************************************************
*/
static int _cbGetData24(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
{
/* 读取点阵数据 */
sf_ReadBuffer(pBuffer, XBF_Font24BaseAdd Off, NumBytes);
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: _cbGetData32
* 功能说明: XBF字体的回调函数, 32点阵
* 形 参: Off - 地址偏移
* NumBytes - 需要读出的字节数
* pVoid - 指针变量,一般用于带文件系统时的FIL类型变量
* pBuffer - 获取字体的点阵数据
* 返 回 值: 0 表示成功 1 表示失败
*********************************************************************************************************
*/
static int _cbGetData32(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
{
/* 读取点阵数据 */
sf_ReadBuffer(pBuffer, XBF_Font32BaseAdd Off, NumBytes);
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: GUI_SetXBF
* 功能说明: 创建XBF字体
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void GUI_SetXBF(void)
{
/* 创建16点阵字体 */
GUI_XBF_CreateFont(&XBF_Font16, /* GUI_FONT类型变量 */
&XBF_Data16, /* GUI_XBF_DATA类型变量 */
GUI_XBF_TYPE_PROP, /* 字体类型 */
_cbGetData16, /* 回调函数 */
&Fontfile16); /* 回调函数参数 */
/* 创建24点阵字体 */
GUI_XBF_CreateFont(&XBF_Font24, /* GUI_FONT类型变量 */
&XBF_Data24, /* GUI_XBF_DATA类型变量 */
GUI_XBF_TYPE_PROP, /* 字体类型 */
_cbGetData24, /* 回调函数 */
&Fontfile24); /* 回调函数参数 */
/* 创建32点阵字体 */
GUI_XBF_CreateFont(&XBF_Font32, /* GUI_FONT类型变量 */
&XBF_Data32, /* GUI_XBF_DATA类型变量 */
GUI_XBF_TYPE_PROP, /* 字体类型 */
_cbGetData32, /* 回调函数 */
&Fontfile32); /* 回调函数参数 */
}
创建XBF字体要用到函数:GUI_XBF_CreateFont,关于这个函数有必要说说,函数的原型如下:
代码语言:javascript复制int GUI_XBF_CreateFont(GUI_FONT * pFont,
GUI_XBF_DATA * pXBF_Data,
const GUI_XBF_TYPE * pFontType,
GUI_XBF_GET_DATA_FUNC * pfGetData,
void * pVoid);
- 第1参数和第2个参数比较好理解,填写我们前面定义的变量就行。
- 第3个参数要特别注意,参数类型一定要跟FontCvt创建时的字体类型对应。此参数有以下五种类型。
GUI_XBF_TYPE_PROP
GUI_XBF_TYPE_PROP_EXT
GUI_XBF_TYPE_PROP_FRM
GUI_XBF_TYPE_PROP_AA2_EXT
GUI_XBF_TYPE_PROP_AA4_EXT
而FontCvt创建的时候有以下七种类型:
对应关系是
GUI_XBF_TYPE_PROP = Standard
GUI_XBF_TYPE_PROP_EXT = Extended
GUI_XBF_TYPE_PROP_FRM = Extended,framed
GUI_XBF_TYPE_PROP_AA2_EXT = Extended,antialiased,2bpp
GUI_XBF_TYPE_PROP_AA4_EXT = Extended,antialiased,4bpp
初学者使用的时候,一定要注意这个问题。另外要注意,字体类型antialiased,2bpp和antialiased,4bpp是不支持XBF格式字体的。
- 第4步是回调函数,用户要在这个回调函数里面实现XBF字体点阵数据的读取,这里是从SPI Flash中读取点阵数据的。
- 第5个参数是回调函数的一个形参,如果XBF文件是存储到不带文件系统的的存储介质中,这个参数是用不到的,如果带文件系统的话,这个参数是要用到的。实际项目中,不推荐将XBF字体存储到带文件系统的存储介质中,实际测试发现,稍大点的字体都会使得界面效果比较卡顿,不实用。如果进一步了解的话,参考emWin教程V1.0版本里面的第20章配套的例子,那个例子是将XBF字体存到SD卡中并使用文件系统Fatfs进行访问的,地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=2932
3、 第3步:加载到SPI Flash后,使用就比较简单了。
用户只需调用函数GUI_UC_SetEncodeUTF8()使能UTF-8编码就可以使用XBF格式的字体了,比如设置按钮的字体,调用如下设置函数即可。
BUTTON_SetFont(hWin, &XBF_Font32); /* hWin是按钮的句柄 */
4、 第4步:最后一步切不可忘记设置汉字显示所在源文件的编码类型,具体MDK和IAR的设置方法请看第28章的28.4小节(本章节配套的例子也是设置的MainTask,c文件),这一步绝对不可以省略。
通过这五步就实现XBF格式字体的显示了。另外还要注意一点,默认情况下,创建XB格式字体,每个字符的点阵数据最大值限制为200字节,可以满足大部分要求。如果加载使用更多字节的字符,通过在文件GUIConf.h添加以下宏定义可修改默认值:
#define GUI_MAX_XBF_BYTES 500 /* 重新设置支持的最大字节数 */
默认的定义在文件GUI_ConfDefaults.h文件里面:
#ifndef GUI_MAX_XBF_BYTES
#define GUI_MAX_XBF_BYTES 200
#endif
29.6 内部Flash和SPI Flash程序调试下载配置(重要必看)
将下面两个地方配置后,就可以像使用内部Flash一样使用SPI Flash进行调试了。并且这种方式可以方便的调试程序,内部Flash和外部Flash都做调试。
29.6.1 将字库文件转换为C数组格式文件
为了方便将bin文件添加到MDK工程中,我们这里使用小软件B2C.exe将其转换为C格式文件(此软件已经放到本章配套例子V7-534_emWin6.x实验_XBF格式全字库生成和使用方法,Unicode编码(SPI Flash RTOS)的Doc文件里面。
转换后生成的文件为font.c :
代码语言:javascript复制const unsigned char _acfont[8277280UL 1] = {
0x47, 0x55, 0x49, 0x58, 0x10, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x20, 0x00, 0xFF, 0xFF, 0x52, 0xFF, 0x05, 0x00, 0x14, 0x00, 0x66, 0xFF, 0x05, 0x00, 0x14, 0x00, 0x7A, 0xFF, 0x05, 0x00, 0x14, 0x00, 0x8E, 0xFF, 0x05, 0x00, 0x14, 0x00, 0xA2, 0xFF, 0x05, 0x00, 0x14, 0x0
省略未写
}
29.6.2 设置字库文件到外部SPI Flash。
下面将流位图文件下载到SPI Flash,需要大家先在这里添加SPI Flash地址范围:
然后设置资源文件到外部SPI Flash:鼠标右击文件分组GUI/Font,选择Options。
29.6.3 下载配置
注意这里一定要够大,否则会提示算法文件无法加载:
我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。推荐使用AXI SRAM(地址0x24000000),因为这块RAM空间足够大。
如果要下载程序到内部Flash和外部SPI Flash里面,需要做如下配置,两个下载算法都要添加进来:
29.7 实验例程说明(RTOS)
配套例子:
V7-534_emWin6.x实验_XBF格式全字库生成和使用方法,Unicode编码(SPI Flash RTOS)
实验目的:
- 学习emWin的的XBF格式全字库的生成和使用方法,Unicode编码。
- emWin功能的实现在MainTask.c文件里面。
实验内容:
1、K1按键按下,串口或者RTT打印任务执行情况(串口波特率115200,数据位8,奇偶校验位无,停止位1)。
2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
(2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
3、默认上电是通过串口打印信息,如果使用RTT打印信息:
MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
#define Enable_RTTViewer 1
4、各个任务实现的功能如下:
App Task Start 任务 :启动任务,这里用作BSP驱动包处理。
App Task MspPro任务 :消息处理,这里用作LED闪烁。
App Task UserIF 任务 :按键消息处理。
App Task COM 任务 :暂未使用。
App Task GUI 任务 :GUI任务。
μCOS-III任务调试信息(按K1按键,串口打印):
RTT 打印信息方式:
程序设计:
任务栈大小分配:
μCOS-III任务栈大小在app_cfg.h文件中配置:
#define APP_CFG_TASK_START_STK_SIZE 512u
#define APP_CFG_TASK_MsgPro_STK_SIZE 2048u
#define APP_CFG_TASK_COM_STK_SIZE 512u
#define APP_CFG_TASK_USER_IF_STK_SIZE 512u
#define APP_CFG_TASK_GUI_STK_SIZE 2048u
任务栈大小的单位是4字节,那么每个任务的栈大小如下:
App Task Start 任务 :2048字节。
App Task MspPro任务 :8192字节。
App Task UserIF 任务 :2048字节。
App Task COM 任务 :2048字节。
App Task GUI 任务 :8192字节。
系统栈大小分配:
μCOS-III的系统栈大小在os_cfg_app.h文件中配置:
#define OS_CFG_ISR_STK_SIZE 512u
系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB
emWin动态内存配置:
GUIConf.c文件中的配置如下:
代码语言:javascript复制#define EX_SRAM 1/*1 used extern sram, 0 used internal sram */
#if EX_SRAM
#define GUI_NUMBYTES (1024*1024*24)
#else
#define GUI_NUMBYTES (100*1024)
#endif
通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
#define EX_SRAM 1 表示使用外部SDRAM作为emWin动态内存,大小24MB。
#define EX_SRAM 0 表示使用内部SRAM作为emWin动态内存,大小100KB。
默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。
emWin界面显示效果:
800*480分辨率界面效果。
29.8 实验例程说明(裸机)
配套例子:
V7-533_emWin6.x实验_XBF格式全字库生成和使用方法,Unicode编码(SPI Flash 裸机)
实验目的:
- 学习emWin的的XBF格式全字库的生成和使用方法,Unicode编码。
- emWin功能的实现在MainTask.c文件里面。
emWin界面显示效果:
800*480分辨率界面效果。
emWin动态内存配置:
GUIConf.c文件中的配置如下:
代码语言:javascript复制#define EX_SRAM 1/*1 used extern sram, 0 used internal sram */
#if EX_SRAM
#define GUI_NUMBYTES (1024*1024*24)
#else
#define GUI_NUMBYTES (100*1024)
#endif
通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
#define EX_SRAM 1 表示使用外部SDRAM作为emWin动态内存,大小24MB。
#define EX_SRAM 0 表示使用内部SRAM作为emWin动态内存,大小100KB。
默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。
29.9 总结
本章节为大家讲解的XBF格式字体是可以用于项目实战的,望初学者务必掌握。项目中不限制将XBF格式字体存储到SPI Flash里面,存储到NOR Flash,SD卡,NAND Flash等也是可以的,只要速度满足要求即可,不过还是建议将其存储到无需文件系统的存储介质中,速度比较快。