头图

1 显示图片

1.1 图片取模

  • 1)生成 bmp 点位图

    • (2)二值化处理:图像 -> 调整 -> 阈值,调整阈值

    • (3)大小调整:图像 -> 图像大小,调整到最大不能超过 64 x 64
    • (4)导出 bmp:文件 -> 导出为 -> 更多 -> bmp
  • 2)打开 bmp 图像:
  • (1)打开 “PCtoLCD2002完美版” 软件
  • (2)打开 bmp 图像:如果打开失败,就把图片用 Windows “画图” 软件重新另存一下。

  • 3)取模:记得选择 “阳码”,要不太丑了。

2 字符集与编码

2.1 字符编码

  • 1)字符集:顾名思义,字符的集合。比如将一副中国象棋随意放置在棋盘上。
  • 2)编码:按照一定的规则给字符集排序。这里的规则即为编码方式,同一个汉字可以有 GB2312、GBK、GB18010,还可以有 UTF-8、UTF-16、UTF-32 编码方式。就好像我们人为规定中国象棋上棋子的位置,这样当我们指定一个位置时,就可以取到已知的棋子。

2.2 ASCII

  • 1)ASCII:1 个字节,其中 32~127 表示空格、数字、标点、字母等可显示字符

2.3 中文编码

2.3.1 GB2312 标准

  • 1)GB2312 标准:

    • (1)小于 0x7F 的编码仍旧为 ASCII
    • (2)取消 0x7F 到 255 的扩展字符集
    • (3)两个大于 0x7F 的字节连在一起表示一个汉字,其中字节的取值范围为 0xA1 ~ 0xFE,可以表示 7000+ 符号,其中汉字 6763 个
    • (4)ASCII 里面原本有的数字、字母等也重新编码成 2 个字节,即 “全角” 字符
  • 2)区位码:GB2312 编码对收录字符进行了 “分区” 处理

    • (1)一共 94 个区,每区 94 个位,一共 8836 个码位
    • (2)GB2312 编码实现:高字节对应 94 个区,低字节对应 94 个位;则 GB2312 的区位码范围为 0101 ~ 9494。同时为兼容 ASCII,区号和位号分别加上 0xA0 偏移,即 0xA1A1 ~ 0xFEFE。
    • (3)汉字的编码范围为 0xB0A1 ~ 0xF7FE。高字节0xB0 ~ 0xF7(区号 16 ~ 87),低字节 0xA1 ~ 0xFE(区号 01 ~ 94)
    • (4)“啊” 字位于 16 区的 01 位,则其区位码为 1601,加上 0xA0 偏移后为 0xB0A1
  • 3)码位示意图:

    • 当生成字库时,要注意 0xXXA0、0xXXFF 要直接跳过,0xD7FA~0xD7FE 要设置占位数据

2.3.2 GBK 编码

  • 1)GBK 编码方式:在 GB2312 标准上增加 14240 个新汉字(包括Big5)和符号
  • 2)GBK 编解码:

    • 编码:不再要求低字节编码必须大于 0x7F,只要高字节大于 0x7F 即可。这样即可兼容 ASCII 和 GB2312 标准
    • 解码:按字节遍历字符串,当遇到一个字符大于 0x7F 时,就再读取它后面的一个字符,两个字符合起来,用 GBK 解码。
  • 3)码位示意图:

2.3.3 GB18030

  • 1) GB18030 的编码使用 4 个字节,它利用前面标准中的第 2 个字节未使用的 “0x30-0x39” 编码表示扩充四字节的后缀,兼容 GBK、 GB2312 及 ASCII 标准。

2.4 Unicode 字符集和编码

  • 1)Unicode 字符集:国际标准化组织(ISO)舍弃地区性方案,重新给全球所有文化使用的符号进行编号,对每一个字符指定唯一的编号(ASCII 字符编号不变),编号从 0x000000 到 0x10FFFF,称为 Unicode。
  • 2)Unicode 字符集只是对字符进行编号,但没有指定对字符的编码,常见的编码方式有 UTF-32、UTF-16、UTF-8。

2.4.1 UTF-32

  • 1)Unicode 字符集每个字符都用 4 个字节来表示。

    • 不兼容 ASCII
    • 浪费存储空间,大量常用字符只需要 2 个字节就能表示。
    • 存储时需要指定字节顺序

2.4.2 UTF-16

  • 1)用 2 个或 4 个字节表示。

    • 0 ~ 0xFFFF 使用 2 个字节表示
    • 将 0xD800 ~ 0xDBFF 映射到 Unicode 字符集中编号超出 0xFFFF 的字符
  • 2)解码:读取两个字节,如果不在 0xD800 ~ 0xDBFF,则以双字节解析,找到对应编号的字符;如果在,则以 4 字节解析
  • 3)节约空间。但仍然不兼容 ASCII,仍有大小端格式

2.4.3 UTF-8

  • 1)变长:1、2、3、4 字节长度
  • 2)编码方式:

    • (1)单字节:最高位为 1,其余位表示 Unicode 编号。即对于 Unicode 编号为 0x0000000 ~ 0x0000007F 的字符,UTF-8 只需要 1 个字节,兼容 ASCII
    • (2)N 个字节:最高字节的前 N 位为 1,第 N+1 位为 0;其它字节前两位为 10;剩余的 N 个字节的其余空位填充 Unicode 编号。
UnicodeUTF-8
编号范围第一字节第二字节第三字节第四字节第五字节
0000 0000 - 0000 007F0xxx xxxx
0000 0080 - 0000 07FF110x xxxx10xx xxxx
0000 0800 - 0000 FFFF1110 xxxx10xx xxxx10xx xxxx
0001 0000 - 0010 FFFF1111 0xxx10xx xxxx10xx xxxx10xx xxxx
0020 0000 - 03FF FFFF1111 10xx10xx xxxx10xx xxxx10xx xxxx10xx xxxx
  • 3)解码:

    • 如果第一个字节 >> 7 为 0,则以单字节解析
    • 如果第一个字节 >> 5 为 0b110,则以双字节解析
    • 如果第一个字节 >> 4 为 0b1110,则以三字节解析
    • 如果第一个字节 >> 3 为 0b11110,则以四字节解析

3 字库 DIY

3.1 生成字库

在编写 OLED 驱动时,需要以 “纵向,先上下后左右,低位在前” 的方式制作 Unicode 和 GBK 编码字库,市面上有不少生成字库的软件,没有找到合适的。

字库

原理简要说明:
  • (1)字符的编码可以理解成整数,如 “路” 在 GBK 编码中为 0xC2B7。那么我们以指定的编码 GBK、大小端的将该整数转换为汉字即可。遍历 GBK 编码的范围的所有整数即可得到所有的 GBK 编码汉字(记得剔除掉其中未编码的数,如 GBK 中的 0xXX7F, 0xXXFF 等位置。)
  • (2)以指定的像素大小(如 16x16)生成一张图片,然后将指定汉字显示到上面,再对图片进行二值化处理(有内容的像素点为 1,无内容的像素点为 0),最后生成一个字节数组。

    • 显示汉字到图片上时可以指定字体,如宋体、楷体等(我试过,只有宋体能看)
    • 图片二值化后生成的 16x16 字节数组如下,看出什么字没有^_-

  • (3)根据指定的显示方式(先左右还是先上下,高位在前还是低位在前,纵向还是横向等),将上述的字节数组转换成点阵数组。

    • 转换时要注意,字节数组每个字节只表示一个像素,而且是横向保存的。如果显示方式是纵向,要注意遍历方式。

3.2 烧录到 W25Qxx

制作的字节在电脑本地,怎么让单片机使用呢?写入到单片机可访问的板上存储器件即可。这里我选择通过 SDCard 写入到板上 W25Q64 中。
  • 1)字库地址分配(8M 的 W25Q64)

    • Unicode 的范围,0x4E00 ~ 0x9FFF,约 2 万个汉字
    • GB2312 的范围,0xB0A1 ~ 0xF7FE,约 6700 个常用汉字
W25Q64 地址字符点阵大小
0x007FF000 ~ 0x0068D000unicode 241480k(0x00172000)
0x0068D000 ~ 0x005E8000unicode 16660k(0x000A5000)
0x005E8000 ~ 0x0056B000unicode 12500k(0x0007D000)
0x0056B000 ~ 0x003C4800gbk 241690k(0x001A6800)
0x003C4800 ~ 0x00309000gbk 16750k(0x000BB800)
0x00309000 ~ 0x0027A800gbk 12570k(0x0008E800)
0x0027A800 ~ 0x001E9800gb2312 24580k(0x00091000)
0x001E9800 ~ 0x001A8800gb2312 16260k(0x00041000)
0x001A8800 ~ 0x00176800gb2312 12200k(0x00032000)

total font_lib_size: 6.53MB(0x00688800)


送南阳马生序
7 声望3 粉丝

余之业有不精、德有不成,非天质之卑,则心不若他之专耳,岂他人之过哉!