汉字字库生成与烧录详解

汉字字库生成与烧录详解

文章目录

资源获取一、介绍字库1. GB23122.GBK

二、生成字库1.打开字库生成软件2.软件介绍3.生成bin字库

三、烧录字库1.打开串口烧录软件2.配置软件3.打开字库文件4.将烧录程序下载到开发板5.开始烧录

三、测试字库1.从flash中读取数据2.直接生成c文件验证3.用winhex软件验证

资源获取

github:链接

一、介绍字库

1. GB2312

GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312。

GB2312收录简化汉字及符号、字母、日文假名等共7445个图形字符,其中汉字占6763个。

GB2312规定“对任意一个图形字符都采用两个字节表示,每个字节均采用七位编码表示”,习惯上称第一个字节为“高字节”,即所谓的区码。第二个字节为“低字节”,即所谓的位码

其编码范围是高位0xa1~0xfe,低位也是0xa1~0xfe;汉字从0xb0a1开始,结束于0xf7fe。GB2312将代码表分为94个区,对应第一字节(0xa1~0xfe);每个区94个位(0xa1~0xfe),对应第二字节。两个字节的值分别为区号值和位号值加32(20H),因此也称为区位码。01~09区为符号、数字区,16~87区为汉字区(0xb0~0xf7),10~15区、88~94区是有待进一步标准化的空白区。GB2312将收录的汉字分成两级:第一级是常用汉字计3755个,置于16~55区,按汉语拼音字母/笔形顺序排列:第二级汉字是次常用汉字计3008个,置于56~87区,按部首/笔画顺序排列。故而GB2312 最多能表示6763 个汉字。点阵库只要按照这个编码规则从0XA1A1开始,逐一建立,每个区的点阵大小为每个汉字所用的字节数乘以94。

定位公式:

Hp=((GBH-0xA1)×94+GBL-0XA1)×(size);

其中GBH、GBL 分别代表GB2312 的第一个字节和第二个字节(也就是高位和低位),size 代表每个汉字点阵所需的字节数,Hp 则为对应汉字点阵数据在字库里面的起始地址。

2.GBK

而GBK内码完全兼容GB2312,同时支持繁体字,总汉字数有2万多个,编码格式如下,每个GBK码由2个字节组成,第一个字节为0X81~0XFE,第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE。其中与GB2312相同的区域,字完全相同。把第一个字节代表的意义称为区,那么GBK里面总共有126个区(0XFE~0X81+1),每个区内有190个汉字(0XFE~0X80+0X7E~0X40+2),总共就有126x190=23940个汉字。点阵库只要按照这个编码规则从0X8140开始,逐一建立,每个区的点阵大小为每个汉字所用的字节数乘以190。

定位公式:

当GBKL<0X7F 时:Hp=((GBKH-0x81)×190+GBKL-0X40)×(size);

当GBKL>0X80 时:Hp=((GBKH-0x81)×190+GBKL-0X41)×(size);

其中GBKH、GBKLL 分别代表GBK 的第一个字节和第二个字节(也就是高位和低位),size 代表每个汉字点阵所需的字节数,Hp 则为对应汉字点阵数据在字库里面的起始地址。

参考链接:详细介绍

二、生成字库

首先,我们需要先去用软件(github里)生成我们需要的字库文件,

1.打开字库生成软件

2.软件介绍

1 我们可以选择我们需要的字体 2 可以选择我们生成字体的大小 3 选择使用标准字库还是自己定义的,自己定义的是点击编辑码表,然后输入自己要使用的字体,标准字库是生成一个标准格式的全部字体 4 这个是取模的大小,一般和字体大小一致。 下面的选项在我这里不需要改动,大家可根据需求进行选择。

3.生成bin字库

生成一个16X16的字库和一个32X32的字库,都是黑体。 可以看这两个字体的大小

三、烧录字库

1.打开串口烧录软件

波特率配置为115200和程序里面的对应

2.配置软件

因为程序的设计,发送255个数据之后最好等待一段时间

设置软件每256字节延时50ms,防止数据丢失,但时间肯定要花费长一点。

3.打开字库文件

在串口助手中打开字库文件 我这里用的是16X16,宋体,GB2312编码

4.将烧录程序下载到开发板

将flash烧录程序下载到开发板 注意: 在下载之前,需要配置好参数,比如下载的字体大小和读取的编码计算公式还有下载的地址等 代码:

u32 fontype = 0x00;

uint8_t flashbuff[132]; // 从flash中读取的数组存放 一个汉字是132字节

/* 从flash中取出指定的字符的地址

*Char_Rx_Buffer: 接收数据的数据

Char_Rx_Length:接收数据的长度

*/

void getAddr(uint8_t *Char_Rx_Buffer,uint16_t Char_Rx_Length)

{

uint32_t offset; // flash字库地址偏移量

uint8_t qh, wh; // 区码和位码

uint16_t x,i; // 接收字符的长度

/* 字模的长宽 字节数 */

uint8_t Word_Touch_High, Word_Touch_Wide, Word_Touch_Size, \

Word_Touch_Size_Half, Word_Touch_Wide_Half;

//单个字模指的是汉字,半个单字模指的是ASCALL码

Word_Touch_High = 16; // 字摸的高共多少位

Word_Touch_Wide = 16; // 字模的宽共多少位

Word_Touch_Wide_Half = Word_Touch_Wide / 2; //半个单字模的位宽// 半个字模的高是一样的

/* 字模的字节数 */

Word_Touch_Size = (Word_Touch_High * Word_Touch_Wide) / 8; //单个字模共有多少字节

Word_Touch_Size_Half = (Word_Touch_High * Word_Touch_Wide_Half) / 8; //半个字模有多少字节

for(x = 0; x < Char_Rx_Length;) //总共有多少个数据

{

//ASCII码最高为:0111 1111

if(Char_Rx_Buffer[x] & 0x80) //判断是否为汉字

{

/* 取出对应的汉字的字节码 */

/* 区码 = bn1 - 160 (160 = 十六进制 0xA0)

位码 = bn1 - 160

bn1,bn2 分别表示汉字机内码的第一个字节和第二个字节 */

// qh = Char_Rx_Buffer[x] - 0xA0; //区码2017-08-13汉字库中包含全角字符

// wh = Char_Rx_Buffer[x + 1] - 0xA0; //位码2017-08-13汉字库中包含全角字符

/* 偏移地址 = (94*(区码-1) + (位码 -1)) * 字节数 */

qh = Char_Rx_Buffer[x] ;

wh = Char_Rx_Buffer[x + 1] ;

u1_printf("%x %x\r\n",qh,wh);

/* fontype 是每个字体存放的起始地址 */

// GB2312

offset = (u32)(94 * (qh - 0xA1) + (wh - 0xA1)) * Word_Touch_Size + fontype; //////通过区位码计算,计算汉字存在FLASH中的位置(在FLASH中的存储汉字+ASCII)2017-08-13

// GBK

// if(wh > 0x80)

// offset = (u32)((qh - 0x81) * 190 + (wh - 0x41) )*Word_Touch_Size +fontype;

// else if(wh < 0x7F)

// offset = (u32)((qh - 0x81) * 190 + (wh - 0x40) )*Word_Touch_Size +fontype;

u1_printf("%x \r\n",offset);

/* 从flash 中读取这个汉字的字节码 */

SPI_FLASH_BufferRead(flashbuff, offset, Word_Touch_Size); //读取FLASH中的一个汉字的字模

x = x + 2; //汉字编码+2(对于汉字的编码:一个汉字用两个码,对于ASCLL的编码:一个ASCLL码用一个码)

for(i = 0;i< Word_Touch_Size;i++)

printf("%x ",flashbuff[i]);

printf("\r\n%d\r\n\r\n\r\n",Word_Touch_Size);

}else{ // 字母

qh = Char_Rx_Buffer[x]; //获取ASCLL码中的编码

//offset= (u32)((94*(0xF7-0xB0)+0xFE-0XA1+1)*Word_Touch_Size+(qh-0x20)*Word_Touch_Size_Half);//计算ASCLL码存在FLASH中的位置(在FLASH中的存储汉字+ASCLL)

offset = fontype + ASCII + (qh - 0x20) * Word_Touch_Size_Half; //ASCII码的起始地址,以实际字库为准。

SPI_FLASH_BufferRead(flashbuff, offset, Word_Touch_Size_Half); //读取FLASH中的一个英文字符的字模

x = x + 1; //英文编码+1(对于汉字的编码:一个汉字用两个码,对于ASCLL的编码:一个ASCLL码用一个码)

for(i = 0;i< Word_Touch_Size_Half;i++)

printf("%x ",flashbuff[i]);

printf("\r\n%d\r\n\r\n\r\n",Word_Touch_Size_Half);

}/* 字母*/

}/* 字符的长度 */

}

字体大小 当烧写的字库不是32X33的,我们需要修改这两个值 这两个值是字库的字体的高和宽,也就是字模大小

Word_Touch_High = 16; // 字摸的高共多少位

Word_Touch_Wide = 16; // 字模的宽共多少位

烧录首地址 当我们烧录的地址不是0x00的时候,我们需要修改下面这个值,修改为字库下载的首地址

u32 fontype = 0x00;

编码 当我们使用的是GB2312编码的时候,不用更改 当我们使用的是GBK编码的时候,把上面的注释掉,用下面的公式

5.开始烧录

简单介绍一下命令行模式和串口模式 命令行模式 用flash -h可以查看帮助文档 然后执行对应的命令可以执行对应的操作 用户自用。 串口模式 只用来烧录字库

两种模式通过一个按键切换。

烧录 在烧录之前,我们需要先格式化flash或者擦除扇区或块,我这里直接格式化 按一下我开发板上的黄色按键,会切换到命令行模式 然后发送命令 格式化命令

flash -f

等一小会,当出现 格式化完成。 再按一下按键,回到烧录模式

烧录模式按文件分为两种方式 二进制文件bin 如果我们烧录的是二进制文件,可以直接烧录 点击发送文件

别的文件(dat) 如果我们是dat结尾或别的结尾的文件,我们需要勾选HEX发送,即以16进制的形式发送数据 写入完成 串口会一直打印写入成功,每256个字节打印一次写成功。 然后我们等待几分钟,当下面的蓝色进度条满的时候,就表示写入完成。 发送完毕

三、测试字库

1.从flash中读取数据

我们需要从烧写的flash中读取你好这两个字的字模的十六进制数据 我们切换到命令行模式 输入你好 可以看到读出了你好的字模数据

2.直接生成c文件验证

直接生成c文件验证 我们再用字库软件自定义生成汉字字模用于验证, 点击编辑码表,输入你好 我们配置软件如下 文件格式我们设置为c文件,方便查看 然后保存文件 之后我们用notepad++打开 flash中数据 然后我们对比这两组数据 发现数据一致,即烧录成功。

3.用winhex软件验证

用winhex软件验证 用winhex打开烧录的gb2312songti16X16的文件, 然后查找偏移量 1a380和12a00的数据 打开位置,跳转到偏移量 如果这里是十进制表示的,需要设置为16进制表示或转换为10进制 执行下面步骤 查找的数据 你 好 对比,发现数据一致,即烧录成功。

相关作品

java 所有事件类型以及事件实现的方法 beat365正规吗

java 所有事件类型以及事件实现的方法

❤️ 583 📅 07-10
电影《冰雪奇缘》 365体育官网全球最大

电影《冰雪奇缘》

❤️ 759 📅 07-27
德国足球队名单世界杯,德国世界杯夺冠阵容 国外365平台

德国足球队名单世界杯,德国世界杯夺冠阵容

❤️ 122 📅 07-10