打印
[应用相关]

跟着原子学习stm32之汉字显示

[复制链接]
592|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
观海|  楼主 | 2021-8-3 09:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
字库显示的整个过程可以概括为:

       根据汉字的GBK码找字库码。根据字库码以bit的形式在显示屏上显示出来。



       整个过程主要包括两个难点:

1、GBK码和字库码的存储。

2、如何根据汉字查找码值,然后显示出来



       解决第一个问题。

       本节的应用是将UNIGBK文件、GBK12文件、GBK16文件从SD卡中移植到W25Q64中,首先关于各个文件的生成请看原子写的《stm32开发指南》中46章介绍。然后程序的开始首先要检测SD卡中各个文件是否存在,如果存在的话,则根据要求做移植,那么问题是移植到哪里呢。对于W25Q64,我的观点是它是一个死的存储机构。你可以随心所遇的选择移植的位置。但有个问题,如果你使用了某个区域做其它用途,如实验数据的记录等,千万不要覆盖了它们的位置。另外要计算下你选取的首地址到W25Q64的最后地址能否足够大盛的下这几个文件。考虑了这两点,你就可以做接下的操作了,那就是判断移植!这里有个小问题,就是在第一次完成移植后,W25Q64中有了字库文件。可以设置一个地址为标志为地址,用来表明当前W25Q64中是否存在字库,这样每次初始化判断一下可以避免字库的重复写入。

       解决第二个问题。

       GBK码是汉字内码扩展规范,字库码(需要自己制作,详细制作方法见原子stm32开发指南)对应GBK码的编码形式的存在。即GBK码中一个汉字占两个字节,第一个字节为 0X81~0XFE,第二个字节分为两部分,一是 0X40~0X7E,二是 0X80~0XFE。
共有23940个汉字。而字库码中一个汉字所占字节数是不固定的,他根据汉字的大小来确定(即使用软件生成字库文件时设置的宽和高决定的)。它是以bit的形式将汉字拼出来,如果要显示的汉字大,则该汉字占用的字节数就多。由于字库码是根据GBK码来制作的,所与两个文件中的汉字顺序是相同的。当我们使用GBK码去查找他对应的要显示的汉字时,需要先通过GBK码计算他在字库中是第几个汉字,然后根据单个字的大小计算字的编码偏移首地址。

       这是汉字显示部分我读原子《stm32开发指南》的一些整理。没涉及到具体。

       在使用汉字显示时,原子在文中还提到了CC936的改编,其中的两个UNI2GBK和GBK2UNI数组单独放在一个文件中生成了一个UNI2GBK.BIN文件。这两个数据有个特点:即4个字节表示一个汉字(uni20em数组是前两个字节为unicode码,后两个字节为其对应的GBK码;oem2uni数组是前两个字节为GBK码,后两个字节为其对应的unicode码),所以除以4,代表一共有多少汉字,然后在srcsrc == p[i * 2]中乘以2 是因为两个字节为一个数组元素,即一个汉字占数组的两个元素。所以对应第N个汉字,它在数组中位置为N*2。最后的输出为c = n ? p[i * 2 + 1] : 0;表明输出查找到的GBK码(unicode码)后面对应的unicode码(GBK码)。

      它的代码是

<span style="font-size:14px;">WCHAR ff_convert (        /* Converted code, 0 means conversion error */
        WCHAR        src,        /* Character code to be converted */
        UINT        dir                /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
        WCHAR t[2];
        WCHAR c;
        u32 i, li, hi;
        u16 n;                         
        u32 gbk2uni_offset=0;                  
                                                  
        if (src < 0x80)c = src;//ASCII,直接不用转换.
        else
        {
                if(dir)        //GBK 2 UNICODE
                {
                        gbk2uni_offset=ftinfo.ugbksize/2;         
                }else        //UNICODE 2 GBK  
                {   
                        gbk2uni_offset=0;
                }
                //if(UK_FLAG)//存在                     
                {
                        /* Unicode to OEMCP */
                        hi=ftinfo.ugbksize/2;//对半开.
                        hi =hi / 4 - 1;
                        li = 0;
                        for (n = 16; n; n--)
                        {
                                i = li + (hi - li) / 2;       
                                SPI_Flash_Read((u8*)&t,ftinfo.ugbkaddr+i*4+gbk2uni_offset,4);//读出8个字节  
                                if (src == t[0]) break;
                                if (src > t[0])li = i;  
                                else hi = i;   
                        }
                        c = n ? t[1] : 0;  
                }
                //else c=0;
        }
        return c;
}                   </span>

       我查看了程序的代码,在原子的例程中,除了改编后的mycc936调用了UNI2GBK文件其它地方没有调用他,程序中也没有间接调用。那么UNI2GBK文件存在的意义是什么?


       在FATFS中存在这样的定义:

<span style="font-size:14px;">#define        _USE_LFN        2                /* 0 to 3 */
#define        _MAX_LFN        255                /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
/   0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
/   1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
/   2: Enable LFN with dynamic working buffer on the STACK.
/   3: Enable LFN with dynamic working buffer on the HEAP.
/
/  The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
/  Unicode handling functions ff_convert() and ff_wtoupper() must be added
/  to the project. When enable to use heap, memory control functions
/  ff_memalloc() and ff_memfree() must be added to the project. */


#define        _LFN_UNICODE        0        /* 0:ANSI/OEM or 1:Unicode */
/* To switch the character code set on FatFs API to Unicode,
/  enable LFN feature and set _LFN_UNICODE to 1. */</span>
       其中的_USE_LFN表示是否支持长文件名,在支持长文件名的情况下,可选择是否把长文件名的的字符数据在FATFS接口上转为UNICODE码。可以看到这是在FATFS中用到了UNI2GBK文件的地方,实际上如果我们仅仅测试将中文名打印到显示屏上的话,是用不到UNI2GBK文件文件的。

       在ARM中文字是以GBK编码存在,但是在WINDOWS系统值,文字的存在形式是UNICODE编码,这样,当应用到FATFS时,UNICODE与GBK的转换就必不可少了!



以上为看原子讲义的小总结,比较笼统,欢迎批评指正


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

4133

帖子

1

粉丝