查看: 803|回复: 0
打印 上一主题 下一主题

Arduino超级LCD、OLED显示库u8glib【二】图形设计

[复制链接] qrcode

25

主题

29

帖子

87

积分

注册会员

Rank: 2

积分
87
楼主
跳转到指定楼层
发表于 2016-4-16 10:53 AM | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  图片看不到戳 这里


通过本文,你将学习到u8glib的工作原理,字体显示原理,还有一些画图函数,最后通过点阵中文字库获取字模,在液晶上显示中文汉字。

u8glib工作方式跟我们自己编写液晶驱动不同,通常,驱动液晶显示要先取字模,将点阵字模转换成字符序列,通过write命令把字符写入液晶的DDRAM,每次送8个比特,也就是八个像素点(不论并口、SPI、I2C接口差不多都这样)。传统方法在液晶上画东西比较费劲,要考虑覆盖、清除问题。u8glib采用不同的方式,虽然它操作起来如此方便,但它没有简单的使用内存缓冲,毕竟,内存对于单片机是非常珍贵的资源(缓存128x64像素要1K字节)!但如果我们把屏幕分成四块,比如左上、右上、左下、右下四部分。第一次,如果画图点在左上就把它缓存,不在则丢弃,这样完成一次完整的draw后,左上块儿就画好了,再把它批量送入液晶显示;接下来再循环3次draw,就完成了整个液晶的显示。于是,我们只用了原来1/4的缓存(256字节)就够了,代价是我们把屏幕画了4次!很多情况下,画图时间并不重要,即使画4次也在数十毫秒内,只要不是特别复杂的画图算法就行。综上,u8glib使用这种叫picture loop的技术,在简化作图和内存消耗上折中。对于大多数128x64的液晶,它分成8个page(page就相当于一个块儿),只需128字节内存,操作显示跟计算机上作图非常接近,大幅度简化了显示编程。

代码(draw函数)只需要关注如何显示内容(XBM示例)
 

在u8g示例中,这段代码就是重复调用draw()完成绘画,最后一页完成以后,nextPage()返回0。
注意,因为draw函数会多次调用,所以不要在draw函数中改变全局变量,也不要让draw运行的时间太长。

u8glib以屏幕左上角的点为零点坐标(x,y)=(0,0),此点跟计算机屏幕作图一致。

常用的绘图函数有以下一些,drawBox(), drawCircle(), drawEllipse(), drawFrame(), drawLine(), drawPixel(), drawTriangle() 等。望名知意就不解释了。
参考Reference:https://github.com/olikraus/u8glib/wiki/userreference

接下来着重介绍一下drawStr(),之前用液晶显示文字,要先通过工具取出字模(大小不同要取多套),然后一点点在屏幕上显示出来。虽可以做成通用函数,但做字模工作量还是很大!u8glib内嵌英文字库,极大简化文字显示步骤。

参看Hellowold 程序draw函数,跟文字显示有两个函数,setFont设定字体,drawStr在哪里显示,后台完成其它复杂工作。

对于惜字(Flash)如金的Arduino(没那么夸张,但30K毕竟也不多),有必要研究一下drawStr的工作方式。示例中有两种字体,切换后发现字体osb21比unifont多出4K多,这就是u8glib不同字体之间的存储差别了,大字体消耗更多的Flash空间。

具体字体空间占用参考说明:https://github.com/olikraus/u8glib/wiki/fontsize 选择合适的字体会节省很多存储空间。注意,字体显示是以字体左下角为起始坐标的。

u8glib字体概念非常复杂,如想深入了解可参考font and string handling:https://github.com/olikraus/u8glib/wiki/tstring 详细介绍英文字体的高度、宽度、对齐方式,以及如何获得字体高度、宽度等。

最后,介绍如何显示中文,中文显示是液晶主要功能之一。单片机几乎不使用矢量字体,计算忒复杂!点阵字体主要存储是问题,GB2312字库需要250KB之多,GBK更多,所以,通常处理方法是只存储显示文字,通过索引获取字模。这种麻烦的方法,直到字库芯片诞生,才彻底解决!
字库芯片通过SPI、I2C、串口等接口跟单片机通信,推荐SPI,因为——速度快!我采购的液晶上自带SPI接口字库芯片,这样可以先通过SPI接口从芯片中读出字幕,再液晶回显,充分发挥SPI的特点。可以跟液晶共用SPI数据接口,片选(CS)接额外一个IO,SPI的MISO用于数据回MCU。

字库的访问方法大致有两种,第一种是输入地址,然后读取一个汉字的32字节点阵;还有一种是连续读,貌似这个用途不大,除了测试,谁会用字库顺序呢! 我用的是JLX-GB2312标准字库,它汉字地址是这样计算的。

其中MSB是汉字的高字节,LSB是汉字的低字节,GB2312编码。关于字符编码可以参看我另一篇:Arduino串口显示中文字符,简述Unicode、GB2312、GBK、UTF-8之间的关系

字库文件的点阵式这样安排

但u8glib的drawBitmap是这样组织的

也就是要把列排序变成行排序(液晶本身通常是竖排序,所以字库大都竖排),必须要转置一下,转换代码有点复杂,需要16字节的缓冲(其实也可以不用缓冲,但那样计算太多,不如缓冲效率高)

不同汉字库获得地址算法不同,这个需要查文档。注意数字“L"结尾,用long类型计算。

为了方便显示字符串,用统一的函数完成中文、英文显示。

OK,至此,可以显示中文的液晶就做好了,注意中文表述方式,并不是直接用中文,详情参考 Arduino串口显示中文字符,简述Unicode、GB2312、GBK、UTF

代码下载戳 这里

参考:
u8glib显示原理(picture loop):https://github.com/olikraus/u8glib/wiki/tpictureloop

使用bdf2u8g显示中文:http://www.makerlab.me/guides/9/articles/51


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

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

本版积分规则

快速回复 返回顶部 返回列表