GD32(6)中文字库

目录

  • 字符显示
  • 中文字符编码
    • GB2312
    • GBK
  • 中文字库
  • 字库生成
  • 字模获取

字符显示

       在OLED和LCD这两篇文章中,我们介绍了通过不同屏幕显示的方法,简单来说都是控制像素点的亮灭或颜色值,通过排列来显示相应的内容。其中显示字符所使用的像素点排列,被称为字模,也可以称为点阵数据。

       在OLED一文的最后,我们介绍了字模的获取工具PCtoLCD,通过该软件可以获得对应字符(包括汉字)的字模,当然英文字符、数字以及特殊字符,一般都将其字模存储在.h文件中,即保存在微控制器内部存储器中,通过ASCII的顺序进行调用,但是,通过这种方法显示中文字符比较困难。

       首先中文字符数量较多,仅常用字就已多达6000个左右,此外,还有众多生僻字和繁体字。其次,因为数量多,因此通过ASCII方式进行顺序排列并检索十分不方便。因此对中文字符的显示,一般通过GBK编码进行排列,下面介绍GB2312编码和GBK编码的使用。

关于GB2312编码和GBK编码的区别可参考彻底搞明白 GB2312、GBK 和 GB18030。

中文字符编码

GB2312

       GB2312简体中文编码表

       GB2312编码方式使用区位码来查找字符,通过将字符分为94个区,每个区含有94个字符,总共8836个编码,表达8836个字符(当然,实际上只有6763 个常用的汉字和字符对应的编码可用)。在使用过程中,字符编码的第一字节(高字节)为区号,第二字节(低字节)为位号,根据对应的区号和位号即可查找到对应的字符。区位码定位图如下图所示,其中16代表的是区号。以“啊”字为例,“啊”字对应的位为01,因此“啊”字对应的区位码为“1601”。由于GB2312编码向下兼容ASCII码,因此,在实际的GB2312编码中,将区号和位号同时加上“0xA0”来区别ASCII编码段。最终“啊”字的GB2312编码为0xB0A1。

GD32(6)中文字库_第1张图片

GBK

       GBK编码是从GB2312基础上产生的,可以保存20000多个汉字,包括生僻字和繁体字,并同时兼容GB2312和ASCII编码方式。

       GBK编码使用1字节或2字节空间来保存字符,使用1字节时,保存的字符与ASCII码对应;使用2字节时,保存的字符为中文及其他字符,在其编码区中,第一字节(区号)范围为0x81~0xFE。由于0x7F不被使用,因此第二字节(位号)分为两部分,分别为0x40~0x7E和0x80~0xFE(以0x7F为界)。并且其中与GB2312编码区重合的部分,字符相同,因此可以说GB2312码是GBK码的子集。

0x7F不使用的原因:0x7F在ASCII中表示DEL,向后删除一个字符。
并且不止0x7F,0x08等控制字符同样需要避免使用。

中文字库

       与显示英文需要提供所有的英文字符一样,显示中文时同样需要提供所有的中文字符,由于中文字符太多,因此其字模一般被统一存储在一个文件中,该文件被称为字库文件,当需要显示某个中文字符时,根据上述的区位码从该字库中取出相应字符并绘制即可。

注意,字库的大小不是固定的(这句话听起来很奇怪,但我是指同一种编码都不一样),字库的大小不仅由编码方式决定(如GBK一般都要大于GB2312),还有字体大小决定。若每个字通过100个像素点决定(也就是10 * 10),那么GB2312的6737个字符,需要 6737 * 100 / 8 / 1024 = 82 KB,这对大部分微控制器来说,都是难以承受的。

字库生成

       中文字库的生成和英文字模的生成相同,可以通过软件快捷生成,当然这里的软件不再是PCtoLCD那样单个字符生成,而是直接生成整个字库。

       字库的生成可以使用“高通字库”,免费,打开后如下图所示。

GD32(6)中文字库_第2张图片

       点击左边的第二项并根据要求设置字模格式即可,参考设置如下:

GD32(6)中文字库_第3张图片

注意:左上角字号的大小需要与预览下面,点阵样式中的点阵宽度和高度相匹配,计算公式为:

字号大小 = 点阵大小 * 6/8

当然,如果不相匹配也不是不可以,但显示出来会奇怪一点,可以在上面的预览界面查看。

       设置结束后点击右下角即可生成字库,生成.c文件的话大小约为8.31MB的数组,一般建议生成Bin文件后将其后缀修改为FON,形成字库文件。除了生成对应文件外,还会生成一个txt文件,里面存放着提示信息。

这里生成的FON文件大约是1.51MB,同样是微控制器难以存储的,因此需要将其存储在外部存储器中。

字模获取

       这里的字模获取是指如何从代码中获取对应中文字符的字模,参考txt文件中的提示信息可得,字库被分为 6 段,以其中第一段“0xA1A1 - 0xA9FE”为例,该段中的某个字符的地址addr计算方法如下,其中94是由于每个区都有94个字符,72是区内每个字符字模的字节数。(24 * 24 / 8 = 72Bytes)

addr = ((gbkH - 0xA1) * 94 + (gbkL - 0xA1)) * 72

       代码参考如下,其中,通过GD25Q16Read是由于字库被存储在GD25Q16芯片中。

void GetCNFont24x24(u32 code, u8* buf)
{
  u8  gbkH, gbkL; //GBK码高位、低位
  u32 addr;       //点阵数据在SPI Flash中的地址
  u32 i;          //循环变量

  //拆分GBK码高位、低位
  gbkH = code >> 8;
  gbkL = code & 0xFF;

  //校验高位
  if((gbkH < 0x81) || (gbkH > 0xFE))
  {
    for(i = 0; i < 72; i++)
    {
      buf[i] = 0;
    }
    return;
  }

  //低位处在0x40~0x7E范围
  if((gbkL >= 0x40) && (gbkL <= 0x7E))
  {
    addr = ((gbkH - 0x81) * 190 + (gbkL - 0x40)) * 72;
    GD25Q16Read(buf, 72, addr);
  }

  //低位处在0x80~0xFE范围
  else if((gbkL >= 0x80) && (gbkL <= 0xFE))
  {
    addr = ((gbkH - 0x81) * 190 + (gbkL - 0x41)) * 72;
    GD25Q16Read(buf, 72, addr);
  }

  //出错
  else
  {
    for(i = 0; i < 72; i++)
    {
      buf[i] = 0;
    }
  }
}

至于这里的code是从哪里来的,GBK编码的文件,对应字符存储的就是code。

你可能感兴趣的:(GD32学习笔记,嵌入式硬件,单片机)