查看: 530|回复: 7

[教程] 写了一个SD卡软字库的类库

[复制链接]

该用户从未签到

发表于 2020-5-1 17:40 | 显示全部楼层 |阅读模式
你如果在一个星期前问我Arduino,我会问你啥是Arduino?

从来没有接触过单片机,对于电子器件的知识也只是停留在初中物理阶段,只知道电阻、发光二极管,其他的就一概不知了。直到一个星期前,一个朋友带着一块电路板来找我。

他问我,怎么样才能在屏幕上直接显示中文。我告诉他,拖个控件,然后Text = “中文”就可以了。然后他从裤兜里掏出一块电路板,另外又从上衣口袋里掏出一块屏幕放在桌上,然后默默的看着我,我也默默的看着他,气氛非常的诡异。

为了打破僵局,我不得不开口问他。兄弟,我只是一个普通的程序员,我不是神仙。他说,我知道。我接着问,兄弟,吃了没?然后我们去了楼下的拉面店,用一碗面的工夫,他给我普及了Arduino的基本知识,吃完他就走了,我付的面钱。

回到楼上,我呆呆地看着桌上这堆象是被压路机碾压过的支离破碎的零件,我忍着眼泪,打开浏览器,开始为期3天的封闭式自我培训。3天后,我红着两只眼睛出关了,顺便把屋子里满地的垃圾清理了一下,感觉终于回到了人间。

通过这3天的恶补,感觉没我想象中那么困难,硬件电路部分几乎可以忽略,因为都是成品的模块和通用的接口,同时也有很多现成的类库可以调用。我的重点大部分都是软件方面的,如何打开SD卡中的字库文件,如何根据编码去找到文字的点阵信息,如何把点阵信息显示到屏幕上等等。确定好思路后,说干就干。

第一步,先搞定基本的数据传输。把这些个支离破碎的零件,一个个用线连起来,然后跑几个例程熟悉一下,单独的测试每个模块,比如怎么读SD卡,怎么在屏幕上画点等等。在选择IDE的时候,本着兼容性以及网上搜索资料的便捷性,一开始我选择的是低版本的1.0.6。但是用下来发现这是我这辈子用过的最差的IDE了,从来没见过这么难用的IDE,还不如直接用记事本写程序算了。最终不得不选择了目前最高的版本1.8.12,才勉强可以写程序。不过和其他常规的IDE比起来,这简直就是个渣渣啊,严重影响写程序的心情。

第二步,搞定字库的读取。网上搜索了一下关于各种字库的格式,最终确定使用bin格式的字库。用GuiTool转换出了宋体16*16的Unicode编码、GBK编码、GB2312编码、普通Ascii编码的几个字库文件,同时网上又下载了一个HZK16的字库文件。不过这个HZK16字库文件不能直接用,要修改一下,因为这个文件只有点阵信息,而没有字库信息。不过这个也不难,直接把GuiTool转换出来的GB2312编码的字库文件的前16个字节(也就是字库信息)复制到HZK16的字库文件最前面就可以了。我用的是试用版的GuiTool,根据这个工具的介绍,试用版会故意缺字,不过在我测试期间也没发现缺哪些字。

第三步,搞定编码转换。因为牵涉到UTF8、Unicode、GBK几种编码之间的转换,UTF8和Unicode之间没问题,毕竟两者都是Unicode编码,只是表现形式不同。GBK就不一样了,这个必须要依靠代码页文件才能转换。Windows、Mac、Linux下,系统自带了代码页文件,你可以直接调用API函数进行转换,非常的简单。但是单片机里面没有这个代码页文件,需要自己从网上去找。我用的是libiconv提供的代码页文件,然后自己重新加工了一下,以便可以在Arduino中迅速的索引这个文件。

第四步,搞定文字排版。比如强制换行、自动换行、换行后的对齐方式,还有就是旋转方向、反色显示等等,其实就是坐标的转换、以及颜色的转换。

最后一步,把所有的程序模块合并在一起,联调一下,修改一些小的BUG,就OK了。

一个星期后,我朋友准时出现在楼下的拉面店,然后用一碗面的工夫,他给我普及了这段时间他在外踏青的事情,吃完他就走了,还是我付的面钱。

回到楼上,我呆呆地看着桌上这堆开发板和零件,想起吃面的时候,他说这些零件就送给你了,我谢谢还没说出口,他唆了根面条就接着说,以后有问题,就不用再跑过来送开发板和零件了,我的眼眶禁不住又开始湿润了。

我写的这个类库有2个文件,SDFont.cpp和SDFont.h。使用的时候,把这两个文件复制到你的目录中,然后#include "SDFont.h"。

类库支持U8g、U8g2、Adafruit_ST7789,在SDFont.h中,有如下代码,选择自己使用的类库就可以了。
#include <U8g2lib.h>
//#include <U8glib.h>
//#include <Adafruit_ST7789.h>

如果你使用的是其他屏幕驱动类库,那么只需要修改构造函数、以及GetDisplayWidth、GetDisplayHeight、DrawPixel函数,分别是用于返回屏幕的宽度、屏幕的高度、画点。

这个是1.14寸ST7789的显示效果,SPI接口
01.jpg

这个是1.3寸SH1106的显示效果,I2C接口
03.jpg

SDFont类库使用起来很简单,首先在你自己的程序中,先初始化SD卡和屏幕的类库,然后调用如下代码,用于初始化SDFont类库。
TSDFont SDFont(&SD, &Screen);

其次使用如下代码,来初始化字库。
SDFont.SetFont("/Unicode.bin");
SDFont.SetFont("/GBK.bin", 936, "GBK", "/Ascii.bin");

初始化字库函数一共有4个参数:
(1)const String strFontFilename:字体文件名
(2)const int nCodePage = -1:代码页,比如936(简体中文),Unicode编码的字库是不需要代码页的
(3)const String strEncodeType = "":字库编码,目前支持GBK、GB2312、GB2312-16(简化版的GB2312字库,不含1-15区(符号、数字区),直接从第16区(汉字区)开始),Unicode编码的字库是不需要再次设置字库编码的
(4)const String strAsciiFontFilename = "":补充字库。GBK、GB2312字库中只有汉字、全角符号等点阵信息,并没有普通的英文、数字、半角符号的点阵信息,所以中英文混合时会造成无法全部显示的问题,这时候就需要一个含有普通Ascii字符点阵信息的补充字库。这个补充字库必须是MBCS非等宽编码,并且和字体文件具有相同的像素高度

最后使用SDFont.DrawText来显示文字,函数一共有11个参数:
(1)int16_t nXpos:文字左上角的X坐标
(2)int16_t nYpos:文字左上角的Y坐标
(3)const char *pcText:文字的内容
(4)const boolean boolAutoWordWrap = true:是否需要自动换行
自动换行
02.jpg

不换行
04.jpg

(5)const uint8_t nWordWrapAlign = 0:换行后的对齐方式,0:和屏幕边缘对齐;1:和上一排文字对齐
和屏幕边缘对齐
05.jpg

和上一排文字对齐
06.jpg

(6)const boolean boolReverse = false:是否需要反色显示
正常显示
07.jpg

反色显示(当中黑色的斜线是拍照时候的频闪造成的)
08.jpg

(7)const boolean boolTransparent = false:背景是否需要透明
不透明
09.jpg

透明
10.jpg

(8)const uint8_t nDirection = 0:文字旋转方向,0:0度;1:90度;2:180度;3:270度
0度
11.jpg

90度
12.jpg

180度
13.jpg

270度
14.jpg

(9)const boolean boolPosBottom = false:是否以文字的左下角为原点坐标
相同起始坐标的情况下,以左上角为原点坐标
15.jpg

相同起始坐标的情况下,以左下角为原点坐标
16.jpg

(10)const uint8_t nWidthScale = 1:文字的横向放大倍率
(11)const uint8_t nHeightScale = 1:文字的纵向放大倍率
横向倍率1,纵向倍率1
17.jpg

横向倍率2,纵向倍率1
18.jpg

横向倍率1,纵向倍率2
19.jpg

横向倍率2,纵向倍率2
20.jpg


该用户从未签到

 楼主| 发表于 2020-5-1 17:45 | 显示全部楼层
类库
example.zip (7.64 KB, 下载次数: 13)

该用户从未签到

 楼主| 发表于 2020-5-1 17:58 | 显示全部楼层
编译环境
系统:MacOS 10.11
IDE:Arduino IDE 1.8.12
U8g:1.19.1
U8g2:2.27.6
Adafruit ST7789:1.5.15
  • TA的每日心情
    擦汗
    2019-11-1 21:03
  • 签到天数: 101 天

    [LV.6]常住居民II

    发表于 2020-5-1 23:54 | 显示全部楼层
    牛批,
    just sounds like from outside the wall
  • TA的每日心情
    开心
    2020-6-4 13:14
  • 签到天数: 64 天

    [LV.6]常住居民II

    发表于 2020-5-2 09:49 | 显示全部楼层
    确实牛逼,我也想搞字库,可是水平不行,学习了,下来试试,感谢楼主奉献,国内好多人放出来的东西都要设置些小障碍,俺水平不行就只能看看了,你公布了对我们是好事
  • TA的每日心情
    开心
    2020-6-4 13:14
  • 签到天数: 64 天

    [LV.6]常住居民II

    发表于 2020-5-2 10:16 | 显示全部楼层
    楼主俺软件真的很凹,看了半天没看明白
    字库BIN文件要考到SD卡使用吗?我买过8脚的IC硬字库如何使用,能给个方案吗?

    该用户从未签到

     楼主| 发表于 2020-5-2 10:47 | 显示全部楼层
    zxy2266 发表于 2020-5-2 10:16
    楼主俺软件真的很凹,看了半天没看明白
    字库BIN文件要考到SD卡使用吗?我买过8脚的IC硬字库如何使用,能给 ...

    是的,需要把字库BIN文件copy到SD卡上,然后程序会从SD卡上读取字库,并显示在屏幕上。

    硬字库我没用过,不过在我三天闭关自我培训期间,大致也了解过。大部分的硬字库是通过I2C或者SPI接口和单片机相连,然后厂家都会提供一个类库,用于获取硬字库中的字符的点阵信息,然后你自己再把点阵信息画到屏幕上去。
  • TA的每日心情
    开心
    2020-6-4 13:14
  • 签到天数: 64 天

    [LV.6]常住居民II

    发表于 2020-5-2 12:03 | 显示全部楼层
    SPI接口接口,我,买的是高通的库芯片,文件大传不上
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    5分钟带你快速了解新一代开发板:M5STACK
    5分钟带你快速了解新一代
    一、什么是M5Stack M5Stack是一种模块化、可堆叠扩展的开发板,每个模块
    创客火首发无人机编队套装,开启不一样的人工智能教育
    创客火首发无人机编队套装
    2017年国务院发布《新一代人工智能发展规划》,提出要广泛开展人工智能科普活动,在中
    这个F()函数是做什么的?
    这个F()函数是做什么的
    如图上,在看代码的时候,发现了这么一个函数,然后后面又一行英文注释。 我用有道翻
    隔离论坛在搞一个开源的arduino墨水屏,值得入手吗?
    隔离论坛在搞一个开源的ar
    amobbs论坛出来了一个众筹的arduino的墨水屏终端,100多块钱,有大神加入了吗? 看着
    两轮自平衡小车的线性CCD循迹总结
    两轮自平衡小车的线性CCD
    继之前的两轮自平衡小车的制作总结(https://www.arduino.cn/thread-99011-1-1.html)
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表