字库制作和烧写

文章目录

资源获取

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进制
执行下面步骤
字库制作和烧写
查找的数据

字库制作和烧写
字库制作和烧写

字库制作和烧写
字库制作和烧写
对比,发现数据一致,即烧录成功。

上一篇:MacOS技巧|Mac如何自定义触控栏Touch Bar?显示Touch Bar教程


下一篇:linux目录操作