【第3版emWin教程】第29章 emWin6.x的XBF格式全字库生成和使用方法(Unicode编码,SPI Flash方案)

教程不断更新中: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格式字体

/* 宋体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格式字体

/*
*********************************************************************************************************
*    函 数 名: _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,关于这个函数有必要说说,函数的原型如下:

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 :

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)

实验目的:

  1. 学习emWin的的XBF格式全字库的生成和使用方法,Unicode编码。
  2. 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文件中的配置如下:

#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 裸机)

实验目的:

  1. 学习emWin的的XBF格式全字库的生成和使用方法,Unicode编码。
  2. emWin功能的实现在MainTask.c文件里面。

emWin界面显示效果:

800*480分辨率界面效果。

 

emWin动态内存配置:

GUIConf.c文件中的配置如下:

#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等也是可以的,只要速度满足要求即可,不过还是建议将其存储到无需文件系统的存储介质中,速度比较快。

微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
原文地址:https://www.cnblogs.com/armfly/p/15194282.html