微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > 嵌入式系统设计讨论 > u8glib中文显示

u8glib中文显示

时间:10-02 整理:3721RD 点击:
在麦知项目中,使用u8glib+m2tklib负责在oled1.3上做显示,屏的控制器是sh1106。
根据MakerLab创客实验室的文章,可以显示中文,但是按照他的说法,将末尾的一位删掉,尽管可以持续显示后面的汉字,但实际上字会缺一小部分,而他的完整例子中的字体好像又没问题。
使用bdf2u8g生成一个汉字:

  1. const u8g_fntpgm_uint8_t c11[47] U8G_SECTION(".progmem.c11") = {
  2.   0,13,13,255,254,0,0,0,0,0,136,136,0,11,255,0,
  3.   0,11,12,24,12,0,255,0,128,68,160,34,192,128,128,87,
  4.   224,20,32,39,224,36,32,199,224,68,32,68,32,68,224};

复制代码


其数据格式,在u8g_font.c中有描述,如下:

  1. /*
  2.   ... instead the fields of the font data structure are accessed directly by offset
  3.   font information
  4.   offset
  5.   0             font format
  6.   1             FONTBOUNDINGBOX width           unsigned
  7.   2             FONTBOUNDINGBOX height          unsigned
  8.   3             FONTBOUNDINGBOX x-offset         signed
  9.   4             FONTBOUNDINGBOX y-offset        signed
  10.   5             capital A height                                unsigned
  11.   6             start 'A'
  12.   8             start 'a'
  13.   10            encoding start
  14.   11            encoding end
  15.   12            descent 'g'                     negative: below baseline
  16.   13            font max ascent
  17.   14            font min decent             negative: below baseline
  18.   15            font xascent
  19.   16            font xdecent             negative: below baseline
  20.   
  21. */

复制代码


这里面说明字体通用描述是17个字节。
对照生成的数据,可以得到每个字节的对应解释。
0 - format 0
13 - 字体外框宽度
13 - 字体外框高度
255 - 字体外框 x偏移 -1
254 - 字体外框 y偏移 254
...
实际上,生成字体数据的第2行,首位置的0是 第17字节数据: 字体x下降;若删掉每行的末尾数字,则 0 变成每个字的末尾像素,显示就为缺角。
第2行数据,0,11,12,24,12,0,255,0,128,68,160,34,192,128,128,87 是对字进行描述。

  1. /*
  2. format 0
  3.     glyph information
  4.     offset
  5.     0             BBX width                                       unsigned
  6.     1             BBX height                                      unsigned
  7.     2             data size                                       unsigned    (BBX width + 7)/8 * BBX height
  8.     3             DWIDTH                                          signed
  9.     4             BBX xoffset                                    signed
  10.     5             BBX yoffset                                    signed
  11. */

复制代码


很好的看到,11是字宽, 12是字高, 24是字数据的尺寸,通过 (11+7)/8×12 ≈24, 后面的数据长度与此相符。因为数是除不尽的,所以末尾224,0xe0是高字节用来表示像素。
这次遇到的问题不算太难,被一行16个数据的表现形式迷惑。当然,主要原因还是对数据组织结构不了解,不知道每行的意义。 了解以后,自然很轻松的找到解决办法。
第32~127的部分,直接用命令生成:

  1. bdf2u8g.exe -b 32 -e 127 abc-12.bdf abc-12 abc-12.c

复制代码

对需要的汉字,使用python生成,在txt中填入汉字和hex unicode:

  1. 确 786E
  2. 定 5B9A
  3. 取 53D6
  4. 消 6D88

复制代码

命令行调用:

  1. G:\17\u>c3 a.txt

复制代码


c3.py代码如下,python2.7.10:

  1. # encoding: utf-8
  2. import os
  3. import sys
  4. import re

  5. def get_c(list):       
  6.         # a 是16进制
  7.         # font =         'unifont'
  8.         #font = 'fireflyR11'
  9.         font = 'abc-12'
  10.         command = "bdf2u8g.exe -b {b} -e {e} {sub} %s.bdf c11 {out}" % font
  11.        
  12.         word, code = list  # 得到字,编码
  13.         out_file = 'c11_%s.c' % code  # 输出文件名后缀, 前缀默认为c11
  14.        
  15.         code = int(code, 16)
  16.         page = code / 0x80  # 页数
  17.         begin = code & 0x00ff
  18.         end = begin
  19.        
  20.         sub_command = '-%s %s'
  21.        
  22.         if begin >  0x7F:  # 使用-l 还是-u
  23.                 sub_command = sub_command % ('u', page)
  24.         else:
  25.                 sub_command = sub_command % ('l', page)
  26.        
  27.         command = command.format(b=begin, e=end, sub=sub_command, out=out_file)
  28.        
  29.         print(command)
  30.         os.system(command)  # 执行命令
  31.        
  32.         # 读取.c文件进行合并
  33.         # 提取{}中内容
  34.         # 正则, \{([^\}]+)\}
  35.         if os.path.exists(out_file):
  36.                 lines = open(out_file).read()
  37.                 pattern = r'\{([^\}]+)\}'
  38.                 m = re.search(pattern, lines)
  39.                
  40.                 if m:
  41.                         return word, m.groups()[0].strip()
  42.                 else:
  43.                         return None

  44. def main():
  45.         if len(sys.argv) != 2:
  46.                 print(u'请输入汉字txt')
  47.                 return
  48.         # 打开txt
  49.         if not os.path.exists(sys.argv[1]):
  50.                 print(u"文件 %s 不存在" % sys.argv[1])
  51.                 return
  52.         # 读取行
  53.         head = ''
  54.         # result = {}
  55.        
  56.         lines = open(sys.argv[1]).readlines()
  57.         out_file = os.path.splitext(sys.argv[1])[0]+'_cvt.c'
  58.        
  59.         No = 0x80;
  60.        
  61.         try:
  62.                 f = open(out_file, 'w')
  63.                 f.write('#include "u8g.h" \nconst u8g_fntpgm_uint8_t c11[55] U8G_SECTION(".progmem.c11") = {\n')
  64.                 write_head = True
  65.                 first_word = True
  66.                 for i, line in enumerate(lines):
  67.                         if line:
  68.                                 line = line.split()
  69.                                 list = [line[0], line[1]]  # ['\xe5\xae\xa2', '5BA2']
  70.                                 w, c = get_c(list)
  71.                                 c = c.split()
  72.                                 del c[0]  # 删掉第1行

  73.                                 pos_first = c[0].index(',')
  74.                                 c[0] = c[0][pos_first+1:]  # 删掉第1个零,字体结构的第17字节

  75.                                 c[1] = c[1] + ','  # 补充末尾逗号
  76.                                 # result[w] = c
  77.                
  78.                                 # 写出到文件

  79.                                 f.write('// ' + line[0] + '\t' + line[1] + '\t\t' +  hex(0x80 + i) + '\n')
  80.                                 for v in c:
  81.                                         f.write(v + '\n')
  82.                                        
  83.                 f.write('};')                               
  84.                 print(u'写%s文件成功。' % out_file)
  85.         except IOError:
  86.                 print(u'写%s文件失败。' % out_file)
  87.         f.close()
  88.        
  89.        
  90. if __name__ == '__main__':
  91.         main()

  92.        

复制代码


生成的文件如下:
// 确        786E                0x84

  1. <blockquote>11,11,22,12,0,255,2,0,243,192,36,64,43,224,114,

复制代码

将括号内容附加到127以后。
在程序中引用:

  1. // 第1行:状态, 档位
  2. const char *stage = "\x80\x81";
  3. const char *power_level = "";
  4. M2_LABELPTR(el_home_stage, "f0", &stage);  // 显示工作阶段

复制代码


汉字显示效果,结尾的像素是完整的,而且可以连续显示:



Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top