6403| 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中,有如下代码,选择自己使用的类库就可以了。 [mw_shl_code=cpp,false]#include <U8g2lib.h> //#include <U8glib.h> //#include <Adafruit_ST7789.h>[/mw_shl_code] 如果你使用的是其他屏幕驱动类库,那么只需要修改构造函数、以及GetDisplayWidth、GetDisplayHeight、DrawPixel函数,分别是用于返回屏幕的宽度、屏幕的高度、画点。 这个是1.14寸ST7789的显示效果,SPI接口 这个是1.3寸SH1106的显示效果,I2C接口 SDFont类库使用起来很简单,首先在你自己的程序中,先初始化SD卡和屏幕的类库,然后调用如下代码,用于初始化SDFont类库。 TSDFont SDFont(&SD, &Screen); 其次使用如下代码,来初始化字库。 [mw_shl_code=cpp,false]SDFont.SetFont("/Unicode.bin"); SDFont.SetFont("/GBK.bin", 936, "GBK", "/Ascii.bin");[/mw_shl_code] 初始化字库函数一共有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:是否需要自动换行 自动换行 不换行 (5)const uint8_t nWordWrapAlign = 0:换行后的对齐方式,0:和屏幕边缘对齐;1:和上一排文字对齐 和屏幕边缘对齐 和上一排文字对齐 (6)const boolean boolReverse = false:是否需要反色显示 正常显示 反色显示(当中黑色的斜线是拍照时候的频闪造成的) (7)const boolean boolTransparent = false:背景是否需要透明 不透明 透明 (8)const uint8_t nDirection = 0:文字旋转方向,0:0度;1:90度;2:180度;3:270度 0度 90度 180度 270度 (9)const boolean boolPosBottom = false:是否以文字的左下角为原点坐标 相同起始坐标的情况下,以左上角为原点坐标 相同起始坐标的情况下,以左下角为原点坐标 (10)const uint8_t nWidthScale = 1:文字的横向放大倍率 (11)const uint8_t nHeightScale = 1:文字的纵向放大倍率 横向倍率1,纵向倍率1 横向倍率2,纵向倍率1 横向倍率1,纵向倍率2 横向倍率2,纵向倍率2 类库 example.zip 字库 Unicode:Unicode.zip GBK:GBK.zip GB2312:GB2312.zip HZK16:HZK16.zip Ascii:Ascii.zip 代码页: 950(繁体中文):CP950.zip 936(简体中文):CP936.zip 932(日语):CP932.zip 949(韩语):CP949.zip 编译环境 系统:MacOS 10.11 IDE:Arduino IDE 1.8.12 U8g:1.19.1 U8g2:2.27.6 Adafruit ST7789:1.5.15 |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed