文章目录
资源获取
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进制
执行下面步骤
查找的数据
你
好
对比,发现数据一致,即烧录成功。