15、nodeMCU学习笔记--u8glib模块·一

作者: 谢mingmin | 来源:发表于2017-01-20 22:41 被阅读3961次

oled  spi  esp8266  nodeMCU

Hello NodeMCU

闲言碎语

终于知道如何调整简书的图片大小了。这回准备说说u8glib模块。这个模块我折腾了好几天才弄懂怎么用。关于这个模块,官方的文档显然没有其他模块讲的详细,在没有接触过u8glib模块的人,看nodeMCU的文档估计是点不亮屏幕的。或许想我一开始一样,只有花屏。

真正要知道如何用还要靠u8glib这个图形库的官方文档。这里有个文档说如何显示一行字符串。

如果不想看英文文档,下面这段代码可以让oled显示一段文字(当然是英文的)。效果就是文章开头的那图片所展示的。

cs  = 8 
dc  = 2 -- D2
res = 0 -- D0
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
gpio.mode(8, gpio.INPUT, gpio.PULLUP)
disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res)
disp:setFont(u8g.font_6x10)

str = "Hello NodeMCU!"
function draw()     
    disp:drawStr(0, 16, str)
end

disp:firstPage()
while (disp:nextPage())
do 
    draw()
end

函数模块

如果说上面的代码看起来有点难度的话。没关系,先看看nodeMCU的u8glib模块的API。模块的API看起来是有点多。但完全不需要看那么多,这里只关注几个API。

|序号|函数名|参数|返回值|
|:--|:--:|:---:|:--:|--:|
|1|i2c.setup()|id, pinSDA, pinSCL, speed|speed|
|2|spi.setup()|id, mode, cpol, cpha, databits, clock_div[, duplex_mode]|1|
|||||
|3|ssd1306_128x64_i2c()|address[, use_delay]|object|
|4|ssd1306_128x64_spi()|cs, dc[, res[, use_delay]]|object|
这里前两个API是硬件接口初始化函数,来自i2c模块和spi模块。i2c模块比较简单,还是说说spi模块把。esp8266有2个spi硬件接口,其中一个用于flash了。因此要使用spi驱动oled的话,就只能用另一个接口了。
HSCLK对应了D5, HMISO对应D6,HMOSI对应D7。

后面两个API则是u8glib的初始化函数,具体的函数名和编译的固件有关,后面还会说到。

u8glib相关的API,nodeMCU的文档并没有详细的介绍。要弄清楚各个API具体怎么用,可能还需要看u8glib的官方文档

这里简单的说一下,开头的源码。这里oled的CS直接接到GND了,所以在配置完spi后,可以把gpio配置成输入,把IO利用起来。当然不配置也OK。

spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
gpio.mode(8, gpio.INPUT, gpio.PULLUP)
disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res)
disp:setFont(u8g.font_6x10)

接着初始化u8glib,返回一个u8glib的object。之后都是围绕object来用,比如用setFont()来设置字体。使用drawStr()来显示字符串。但是,想要实现显示,还需要类似于下面的代码。u8glib官方称其为Picture Loop

disp:firstPage()
while (disp:nextPage())
do 
    draw()
end

因为嵌入式设备的RAM很有限,所以u8glib采用了多种内存操作方式。具体怎么操作,应用层不用理会。u8glib会循环写入显存,以实现显示。在循环开始前,需要使用firstPage(),然后等待写入结束。当nextPage()返回0,则表示写入完成。

实际上,这段代码要放在主循环里面,才能刷新屏幕的显示内容。有了这些感性认识后,我就可以开始实际了。

实践一下

开始实践之前,你可能需要重新编译一个固件!这里我们可以选择云编译

Paste_Image.png
I2C和SPI至少要选择一个。再者就是本文的主角——u8glib模块,选择这个模块后,会多一个U8G options栏目,用来选择字体和驱动IC。需要根据使用的液晶驱动IC选择对应的xxx_i2c和xxx_spi。

还有就是选择字体。点击select会弹出一个字体窗口,里面有很多字体可以选择。可以随意选择自己喜欢的字体。不过,不要选太多。同时注意字体的大小,别选择了大字体后没法正常显示。最后,千万要把字体名字记录下来千万要把字体名字记录下来千万要把字体名字记录下来

准备工作做完后,就可以开始code了。先从几个简单的画图API开始。代码有点长,这里面涉及的函数包括了:

cs  = 8 -- GPIO15, pull-down 10k to GND
dc  = 2
res = 0
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
gpio.mode(8, gpio.INPUT, gpio.PULLUP)
disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res)
disp:setFont(u8g.font_6x10)

local s = 0
function draw(state)     
    if state == 0 then 
        disp:drawStr(0, 15, "drawBox")
        disp:drawBox(0, 23, 10, 20)
    elseif state == 1 then
        disp:drawStr(0, 15, "drawCircle")
        disp:drawCircle(36, 36, 10)
    elseif state == 2 then
        disp:drawStr(0, 15, "drawDisc")
        disp:drawDisc(36, 36, 15)
    elseif state == 3 then
        disp:drawStr(0, 15, "drawEllipse")
        disp:drawEllipse(60, 30, 20, 10, U8G_DRAW_ALL)
    elseif state == 4 then
        disp:drawStr(0, 15, "drawFrame")
        disp:drawFrame(60, 20, 20, 30)   
    elseif state == 5 then
        disp:drawStr(0, 15, "drawLine")
        disp:drawLine(5,26, 25, 40)
    elseif state == 6 then
        disp:drawStr(0, 15, "drawStr")
        disp:drawStr90(60, 20, "drawStr90") 
    else  
        disp:drawStr(0, 15, "drawTriangle")
        disp:drawTriangle(14,20, 45,32, 9,42);    
    end
end
disp:begin()
tmr.alarm(0, 1000, tmr.ALARM_AUTO, function()
    if s == 7 then
        s = 0
    else 
        s = s + 1
    end
    disp:firstPage()
    while (disp:nextPage())
    do 
        draw(s)
    end
end)

draw函数中切换的使用u8glib中的几种画图函数。然后使用一个定时器来执行Picture Loop以刷新屏幕。

把上面的代码save到nodeMCU中就可以看到屏幕不断的变化了。更多的内容可以查看U8glib Reference Manual。当然了,nodeMCU的u8g模块并没有完全实现u8glib库的全部API,具体可以看Unimplemented Functions

这回就先到这里吧,回头我继续研究一下u8glib。看看有没有什么高级点应用。

一点问题

使用drawStr()函数,这样写disp:drawStr(0, 0, "drawFrame")是看不到屏幕显示字符串的。只有调整一下Y坐标到16左右才可以正常显示。

更多内容

↑ 点击上面的标题可用查看同文集的其它文章。

相关文章

网友评论

  • 汤汤_f6ab:你好,最新nodencu build上u8g变成u8g2,我碰到问题是disp:begin (a nil value)不知道怎么解决了
    汤汤_f6ab:@谢mingmin 谢谢,看过api文档,里面没有找到关于firtpage的东西,能给个参考吗?晚上找半天也只有你这篇是写spi的,非常感谢。
    谢mingmin:@汤汤_f6ab 可能是api变了,请看文档
  • 2e72401c54b0:大神你好,碰到个问题请教一下,我的板子连不上wif
    wifi.setmode(wifi.STATION)
    wifi.sta.config("tashan","85166ggg2")
    wifi.sta.autoconnect(1)
    报错:lua: init.lua:4: bad argument #1 to 'config' (config table not found!)
    stack traceback:
    [C]: in function 'config'
    init.lua:4: in main chunk
    [C]: ?
    2e72401c54b0:@谢mingmin 感谢回复 ~~
    谢mingmin:@快乐就好_65ce 看文档,可能api有变化
  • 3c2ad4b10834:你好,请问这显示屏跟怎么接线?能否给个接线图?谢谢!
    谢mingmin:@dahai2626 不同屏幕的接口丝印不一样,没有参考意义。

    HSCLK对应了D5, HMISO对应D6,HMOSI对应D7

    根据实际屏幕对应接上就行了
  • WiToSmart:请问这个库怎么来调整字体的大小啊
    谢mingmin:@WiToSmart 换字体😅
  • e70c0daab64f:请问下i2c如何向寄存器写入数据呢,官方文档上有i2c读取寄存器的程序,但是想寄存器写入数据没有,自己也尝试写了下,但是好像并没有用,不知道哪里有问题,这里是我写的读取寄存器的代码:
    function write_reg(dev_addr,reg_addr,shuju)
    i2c.start(id)
    i2c.address(id, dev_addr, i2c.TRANSMITTER)
    i2c.write(id,reg_addr)
    i2c.write(id,shuju)
    i2c.stop(id)
    end

    请教下大神
    e70c0daab64f:@谢mingmin 已经解决问题啦。将sda,scl换成了4,3管脚就可以了。也很奇怪为什么1,2管脚就不能读取MPU6050的数据,但是却可以读取其他i2c器件的数据(成功试过)
    谢mingmin: @毅之力_d4d2 你单独用write看看咯。有示波器的话可以看看波形
  • Depen大鹏:屏幕的最上边一行不能显示的原因找到了吗?我的屏也是这样,求解。
    谢mingmin: @Depen大鹏 后一篇文章说了
  • Depen大鹏:好像是我线插错了,重新插了一遍OK了。
  • Depen大鹏:我手里有一块屏,但是RES引脚没有引出。我看到官方文档上说RES是可选引脚,于是就在没有接RES的情况下运行阁下的代码,结果显示的是花屏。不知道问题出在哪里?请教了。
  • fe02c8d3e422:请问下这块屏的线是如何接的?
    能不能支持中文字体?
    fe02c8d3e422:spi和i2c,这个我不明白,不过屏是参照上面的图片买的。
    谢mingmin: @oksonic D5和D7是spi通信的,不同屏幕丝印不一样。另外,确定你的屏幕可以用spi,有些可能是I2C的
    谢mingmin: @oksonic 编译的字体不带中午的,如果要显示中文,可以以图片的形式来弄。
  • 6a94709ccc80:大神更新的好快
    谢mingmin: @河边的 算不上大神,只是有空的时候就写写文章,频率不可控😂

本文标题:15、nodeMCU学习笔记--u8glib模块·一

本文链接:https://www.haomeiwen.com/subject/ypmbbttx.html