STM32工作笔记0069---汉字显示实验

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

这里主要说这个GBK编码

这里举个例子,比如我要显示0这个字,那么

高我要用16位,也就是2个字节,每个位用来代表屏幕上的一个点是1的时候就是亮,然后0的时候就不亮

那么宽度用8个位,这样的话,也就是,一共需要8*16 =128个位就够了,然后

这需要多少个字节呢,就是128/8=16,16个字节就可以显示出这个0来.

也就是我用16个字节,可以描述这个16*8的字体.

这个可以用这个取模软件来得到这个汉字的点阵数据

找到这个软件

看看这个软件,可以看到,这里输入以个0那么上面就显示出来了

这个时候,这里咱们知道是16*8的,可以看到对应英文长宽比是8*16

那么高是16的话,他有一个方向问题,比如这里

16位是两个字节,每个字节,都是从下面到上面,也就是从下面开始是第0位,然后到第7位

也就是这样的:

第一字节    第三字节

7                     7

6                     6

5                     5

4                     4

3                     3

2                     2

1                     1

0                     0

第二字节    第四字节

7                     7

6                     6

5                     5

4                     4                     

3                     3

2                     2

1                     1

0                     0

是这样排列的.

可以点击这里有个取模走向,可以看到,就跟上面画的一样,

他就是左上角上面是第一个字节,然后从下到上0到7位,

然后第二个字节左上角下面也是从下到上0到7位

然后右边上面开始,第三个字节也是从下到上0到7位

然后右边下面开始,第四个字节也是从下到上0到7位

然后点击生成字模就生成汉字的,点阵数据了

然后这里还可以改变现实的样式:

然后再点击生成字模

然后copy出来看一下

可以看到

一共是16个字节.


0X00,0X00,0X07,0XF0,0X08,0X08,0X10,0X04,0X10,0X04,0X08,0X08,0X07,0XF0,0X00,0X00;00 最后这个00是结尾不用管.

可以看到第一个字节是0000 0000 第二个字节也是0000 0000可以看到第一列的两个字节也就是

第一个字节,第二个字节都是0,没有亮的

然后,再看第三个字节开始,0X07 0000 0111,就开始,前5是0,第0位到第2位是1,可以看到就是通过这样把这个字显示出来的.

但是数字是16*8的,汉字是16*16的,这个要搞明白

然后可以看到比如这里如果我要显示一个开字,那么就按照上面的数据,显示就好了

然后:

其他汉字的显示也是一样的就是找到这个汉字内码,然后

去找到对应的点阵库,然后去解析,然后显示就可以了

原理是这样的,就是,找到GBK的编码,比如是1,然后根据这个1,去内存中找到对应的地址,然后把点阵数据取出来

然后显示出来就可以了.

每个GBK码由2个字节组成,第一个字节为0X81~0XFE,第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE

我们把第一个字节代表的意义称为区,那么GBK里面总共有126个区(0XFE-0X81+1),每个区内有190个汉字(0XFE-0X80+0X7E-0X40+2),总共就有126*190=23940个汉字。

这里最小的编码就是0x8140 然后一直到0xFE7E

一共有23940个汉字,几乎包含了所有的汉字.

这里当高位是:0X81的时候,那么低位有190个汉字.

这里为什么有190个字,因为上面说了:

第一个字节为0X81~0XFE,第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE

 第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE。这个是关键.

然后我们就可以把汉字的编码,存储到SPI Flash中去.

然后再去读取,这样就可以实现任意汉字的显示了.

我们可以给区编码,比如区1开始一直到区126.

我们可以把这个编码存储到SPI Flash中去,作为一个字库来使用.

他是这样取的,比如咱们说有126个区,每个区有190个汉字,那么

这里一个汉字的高位减去0X81这个,其实就是,这个汉字目前所在是哪个区里,

GBKH-0X81这个就是汉字的区,比如一个汉字的高位是0X82那么他就是处于第0X82-0X81=1的这个区.

然后

然后找到对应的区以后,然后再

GBKL<0X7F时:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size*2)

 GBKL>0X7F时:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size*2)

如果地址从0开始的话,那么(GBKH-0x81)是找到对应的区,然后

要获取这个区对应的地址,其实就是(GBKH-0x81)*190就获取这个区对应的地址了.

然后GBKL-0X40,这个是这个汉字,对应的偏移地址,这样就获取了

因为每个汉字是两个字节,所以这里还要*2

然后还跟对应的SIZE有关系,还得看字体的大小,所以这里

*(size*2)

GBKL<0X7F时:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size*2)

经过这个计算,就是对应的这个汉字的起始地址了.

然后

 GBKL>0X7F时:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size*2)

这里为什么GBKL-0X41,去取偏移量的时候多减去了一个1,是因为:

第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE

前面说了,这里第二部分是从0X80开始的,也就是忽略了0X7F

所以这里就多减去了一个1.

上面说了汉字内码,接着要做一个点阵库,

做了点阵库就可以查找汉字了

点阵字库的制作方法,这里有个软件

然后

打开这个软件

打开这个软件,然后可以看到可以选择是什么编码,这里选择GBK

然后宽和高也可以设定,然后字体大小,问什么这里字体大小是12呢?

咱们说了,咱们的汉字对应的是16*16,那么对应的电脑端的字体是:

16*6/8=12

电脑端的字体和这个点阵字体是有区别的,需要换算一下.

这里我们选择模式,这个模式,选择取模方式2,可以看到,这个取模方式2,就是咱们上面讲的

左上角上面是第一个字节,低位到高位,从下到上

左上角下面是第二个字节,低位到高位,从下到上

也就是字节高位在前.

其他的模式这里就不说了,这里我们采用纵向取模方式2 .

然后

然后点击创建,就可以创建出整个汉字的字库了,点创建的时候选择一个目录,保存就可以了

现在咱们知道了汉字内码,创建了点阵库,然后就可以去点阵库中查找,某个汉字,

然后去解析和显示了,但同时我们还要把这个字库,写入到

SPI Flash中去,这个需要用到文件系统,读取这个字库,然后写入到

SPI Flash中去.

这个程序过程是这样的:

首先这个

u存字库(fontupd.c):文件是用来存字库的

做好字库。刚才已经做了
将字库 GBK12 GBK16 GBK24 依次写入 SPI FLASH 连续地址: update_font ()
字库写入完毕之后,做标记: ftinfo.fontok =0XAA; 这个就是做个标记,把字库写到什么位置了.
 

第二部分:

这里显示汉字,显示汉字的时候

Show_Str -> Show_Font -> Get_HzMat -> 解析显示。

这里:

Show_Str这个的参数,可以是字符也可以是汉字,如果判断是字符,就去调用LCD去显示了(这部分课程后边补上)

如果是汉字的话,就去调用

Show_Font

然后这个函数就去调用Get_HzMat,去获取这个汉字的,点阵数据,然后解析去显示.

可以看到这个是生成的字库文件

这里我们有以前做好的字库,可以去看看

可以看到这个字库大小是766080

然后

咱们看一下刚才生成的文件的大小,也是

766 080

大小是一样的,也就是,实际上,他们是一样的文件

然后,把这个文件改个名字,改个扩展名,就可以了FON,他就变成了一个字库文件了.

然后咱们把这个字库文件放到SD卡中,然后,咱们的程序就会从SD卡中,

读取这个文件,就会把这个文件写到SPI Flash中去.

然后去看一下汉字显示实验的程序:

打开这个程序

可以看到这两个文件

每个文件的作用图上有.

可以看到在main函数中

首先去调用这个font_init()这个函数

然后去看看这个函数

可以看到这个初始化这里,首先去调用:

W25QXX_Init()这个初始化SPI Flash

然后,去对应的地址区读取,读取到结构体里

可以看到这个结构体实际上是字体的一些信息.

然后再去看一下这个FONTINFOADDR

这个是

这个是什么意思呢,咱们知道我们这里的STM32F103系列,这里有

16M的地址.,那么这里FONTINFOADDR这个指定了再1024*1024*12

1024*1024   

1024字节 *1024=的单位就是m了

然后*12就是从12m的地方开始写入字库

可以看到前12m是作为文件系统使用,所以这里从12m的地址开始写.

可以看到这里:

实际上就是:
从FONTINFOADDR这个12m的地址做为起始地址,开始读取,然后

读取8个u8 ,8位然后 32位的有8个

那么一共就有1+4*8=33个字节.

然后再去判断:

这个fontok是不是0XAA,因为0XAA的意思是,正常读取这个汉字了就返回0,如果不是的话就是这个字库中不存在这个汉字

就返回1.

然后再回到main函数中去看:

如果这里我们检查字库失败了,也就是没有检查到字库,那么

就继续往下走,

也就是需要从SD卡中去进行加载字库

可以看到首先初始化SD卡,SD_Init()

然后

这里调用update_font也就是去调用这个函数,去更新字库

也就说,首先咱们要插入SD卡,然后,在对应的目录中放上做好的字库文件

然后调用update_font的时候,他就会去加载这个字库到flash中去了

然后:

可以看到这个函数中去更新字库,那么

实际上更新的过程,就是去使用文件系统去更新.

可以看到更新每个字库,实际上是使用的updata_fontx()这个函数

实际上就是前面的这个updata_fontx这个函数.

实际上是根据

这里定义的,这几个路径,然后根据路径

可以看到先去打开这个文件,然后把这个字库的信息保存在

fitinfo这个变量中去了.

然后读取这个字库以后,就可以

把这个字库然后可以看到W25QXX_Write(),这样就写入了到flash中去了

而且这里知道了总的大小,同时也知道了当前已经读取到哪个字了,那么就可以显示出一个进度条来.

然后可以看到这里就把这个标志位,

0XAA也写入到了这个Flash,就是这个保存字库信息

那么这里咱们已经把字库保存到flash了,那么怎么去调用呢,接下来

这里就有这个Show_Str这个函数

去看看这个函数

这个函数中可以看到,先去判断,这个字符是,一个特殊字符还是一个汉字

如果这里判断是个文字的话,那么就去调用下面的显示汉字的

Show_Font()这个函数去显示汉字,如果是字符,就去调用LCD_ShowChar()

这个LCD屏幕的一个函数.(LCD部分的教程后面会补上.)

可以看到如果是个汉字的话,就去调用这个Show_Font这个函数就可以了

然后再去看这个Get_HzMat这个函数,这个函数,用来获取汉字的点阵数据

可以看到用这个函数就可以获取这个点阵的数据,实际上他就是根据前面咱们说的那个算法,去找到这个汉字的地址,然后

去读取这个汉字的数据,点阵数据.

可以看到这个函数的过程就是前面说的:

可以看到,这个不同的Size,他对应的调用的算法也是不一样的.

然后可以看到,通过Get_HzMat这个函数,得到对应的点阵数据以后

可以看到接下来就可以根据这个点阵数据去屏幕上画内容了

用CD_Fast_DrawPoint(),来画点的方式,来画出这个汉字来.

注意,这里汉字显示的实验,是这两个文件,然后这里没有一行一行的讲,因为代码比较多,所以这里只说一个思路

说一个设计的原理和思路,如果自己要做字库的话,要去仔细看代码

那接下来,如果咱们要自己做一个36号的字体怎么做?

首先要生成字库

 

字库做好以后,需要修改咱们之前的代码,首先:

这个结构体需要修改的,要加上,支持36号字体的支持.然后

更新字库的时候也需要修改

让他去加载自己做的36号字库

然后字库加载以后,再去看看显示也需要修改:

这里要添加,对36号字体的显示.

这个获取点阵数据的地方也需要修改.

要思路清晰才能改,对于汉字显示就说到这里.

然后再去说一下这个FATFS这个文件系统,修改了一些东西

打开上一讲的代码:

这个FATSF实验,可以看到上一讲的代码中有两个很大的数组,如果这样写的话,很占用flash

那么就可以这样,把这两个大的数组合并以后,然后做成一个bin文件,可以用下面的这个工具

来做这个bin文件

可以看到代码中,有这两个数组,可以把这个两个数组放到一起,然后,用这个软件

打开以后,把这个文件转换成一个bin文件

转换以后,咱们下面就写了这个myc936.c这个文件

可以看到原来的数据,都要记录,每个数据是什么意思,然后咱们把这个数据保存成bin文件以后,

可以看到这个myc936.c这个文件就是去这个flash中去读取了,不跟以前一样,直接操作数组了.

对于,LCD,FATFS,等的教程后面补上.

猜你喜欢

转载自blog.csdn.net/lidew521/article/details/108418697