查看: 239|回复: 5

[讨论] 写了一个SD卡软字库的类库

[复制链接]
你如果在一个月前问我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中,有如下代码,选择自己使用的类库就可以了。
[C++] 纯文本查看 复制代码
#include <U8g2lib.h>
//#include <U8glib.h>
//#include <Adafruit_ST7789.h>


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

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

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

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

其次使用如下代码,来初始化字库。
[C++] 纯文本查看 复制代码
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:是否需要自动换行
自动换行
173231zgiu9zbxugwrumy6.jpg

不换行
173231gxzaflx19l11flbs.jpg

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

和上一排文字对齐
173231gcirhpehg2qherh2.jpg

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

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

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

透明
173231u33voadxeeo5u7xu.jpg

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

90度
173231ohz7w67htqpo701j.jpg

180度
173231jwww618gbn6tr0nw.jpg

270度
173231k8l1nfaaa1v0t0nj.jpg

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

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

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

横向倍率2,纵向倍率1
173232rfem4hezts84xjnj.jpg

横向倍率1,纵向倍率2
173232e994f7x904abeezp.jpg

横向倍率2,纵向倍率2
173232w4nqczns88d5wn8z.jpg


类库
example.zip (7.64 KB, 下载次数: 7)

rzyzzxw  版主

发表于 2020-6-16 12:17:19

喜欢开头的故事
回复

使用道具 举报

hnyzcj  版主

发表于 2020-6-16 17:24:46

rzyzzxw 发表于 2020-6-16 12:17
喜欢开头的故事

结尾的你不喜欢吗
回复

使用道具 举报

铁熊  初级技神

发表于 2020-6-16 17:26:59

好玩的故事,硬核的技术!好文章要点赞支持
回复

使用道具 举报

rzyzzxw  版主

发表于 2020-6-16 18:10:59

hnyzcj 发表于 2020-6-16 17:24
结尾的你不喜欢吗

太硬核,咬不动
回复

使用道具 举报

20060606  高级技匠

发表于 2020-8-1 05:17:29

wow,您的进步够快的
回复

使用道具 举报

高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2020 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail