文章目录
前言
在使用 NodeMCU 时需要直观显示 NodeMCU 连入网络后分配的 IP 地址,所以采用 OLED 作为 NodeMCU 的显示屏。网络上的资料大部分是 Arduino 开发板使用 OLED,所以在使用过程中也遇到了不少的坑。
使用的开发环境为 Arduino IDE
另外,ESP8266物联网教程强烈推荐太极创客!!
太极创客官网网址:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/
所用器件型号
-
开发板
ESP8266 NodeMCU 1.0
相关介绍
-
OLED
优信电子 1.3寸 OLED 7管脚 SPI通信
开发环境搭建
安装 ESP8266-NodeMCU开发板驱动
请参考太极创客教程:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/install-esp8266-nodemcu-driver/
安装 Arduino ESP8266包
请参考太极创客教程:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/nodemcu-arduino-ide/
安装 Arduino U8g2 库
U8g2 库介绍
U8g2是用于嵌入式设备的单色图形库。
支持的显示控制器:SSD1305,SSD1306,SSD1309,SSD1316,SSD1322,SSD1325,SSD1327,SSD1329,SSD1606,SSD1607,SH1106,SH1107,SH1108,SH1122,T6963,RA8835,LC7981,PCD8544,PCF8812,HX1230,UC1601,UC1604,UC1610,UC1611,UC1617,UC1701,ST7511,ST7528,ST7565,ST7567,ST7571,ST7586,ST7588,ST75256,ST75320,NT7534,ST7920,IST3020,IST7920,LD7032,KS0108,KS0713,SED1520 等)
U8g2 还包括 U8x8 库。 U8g2 和 U8x8 的功能包括:
- U8g2
- 包括所有图形过程(线/框/圆绘制)。
- 支持多种字体。 几乎对字体高度没有限制。
- 需要微控制器中的一些内存来呈现显示。
- U8x8
- 仅文本输出(字符)设备。
- 仅允许每个字符使用固定大小的字体(8x8像素)。
- 直接写入显示。微控制器中不需要缓冲区。
安装 U8g2
点击 Arduino IDE 工具
-> 管理库
搜索 U8g2
并安装。
U8g2 库是 U8glib 库的迭代,支持更多种类的开发板,就比如 U8glib 不支持的 NodeMCU 开发板。
U8g2 参考文档:https://github.com/olikraus/u8g2/wiki/u8g2reference
连线
NodeMCU引脚说明
参考自太极创客:
ESP8266 芯片有17个 GPIO 引脚(GPIO0~GPIO16)。这些引脚中的GPIO6~GPIO 11被用于连接开发板的闪存(Flash Memory)。如果在实验电路中使用 GPIO6~GPIO11,NodeMCU 开发板将无法正常工作。因此建议不要使用 GPIO6~GPIO 11。
所以如果我们采用软件模拟 SPI 通信的话,最好不要将 OLED 引脚接到 GPIO6~GPIO11
接线
我们使用 NodeMCU上 的 GPIO 引脚软件模拟 SPI 通信。
接线如下:
GND
->GND
VCC
->VCC
D5
->CLK
D7
->MOSI
RST
->RES
D1
->DC
D8
->CS
测试
类声明
我们先看下 OLED 控制类的名称构造规则,部分翻译自官方文档:
序号 | 描述 | 例子 |
---|---|---|
1 | 前缀 | U8G2 |
2 | 显示控制器 | SH1106 |
3 | 显示名称,一般包含分辨率和厂商 | 128x64_NONAME (不是 U8g2 指定的厂商则为 NONAME ) |
4 | 缓存大小 | 1 |
5 | 通信方式 | 4W_SW_SPI |
这些部分用“ _”连接。 该示例的完整构造函数名称为 U8G2_SH1106_128X64_NONAME_1_4W_SW_SPI
缓存 | 描述 |
---|---|
1 |
显示存储器中只有一页存储在微控制器 RAM 中。 使用 firstPage()/ nextPage() 循环在显示器上绘图。 |
2 |
与1 相同,但在微控制器RAM中保留两页。 这将比1 快两倍。 |
F |
将完整显示帧缓冲区的副本保留在微控制器 RAM 中。 使用 clearBuffer() 清除RAM和 sendBuffer() 将微控制器 RAM 传输到显示器。 |
只有在微控制器中有足够的 RAM 时,才可以使用完整的缓冲区 F
选项。 在具有少量 RAM 的微控制器上使用选项1
或 2
。 如果一页没有内存,则可以使用 u8x8 API
通信协议是构造函数名称的一部分(请参见上文)。 支持以下通信协议:
通信方式 | 描述 |
---|---|
4W_SW_SPI |
软件模拟 4线(时钟线,数据线,CS 和 DC)SPI |
4W_HW_SPI |
硬件 4线(时钟线,数据线,CS 和 DC)SPI(基于Arduino SPI库) |
2ND_4W_HW_SPI |
如果支持,则使用第二个4线硬件 SPI(基于Arduino SPI库) |
3W_SW_SPI |
软件模拟 3线(时钟线,数据线和 CS)SPI |
SW_I2C |
软件模拟 I2C / TWI |
HW_I2C |
基于Arduino Wire 库的硬件 I2C |
2ND_HW_I2C |
如果支持,使用第二个硬件 I2C(Arduino Wire库) |
6800 |
8位并行接口,6800 协议 |
8080 |
8位并行接口,8080 协议 |
构造函数的第一个参数为显示分配基本布局:
Layout | Description |
---|---|
U8G2_R0 |
不旋转,横向 |
U8G2_R1 |
顺时针旋转90度 |
U8G2_R2 |
顺时针旋转180度 |
U8G2_R3 |
顺时针旋转270度 |
U8G2_MIRROR |
无旋转,横向,镜像显示内容 |
所以我的 OLED 控制类根据型号参数和接线方式这样声明:
U8G2_SH1106_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/14, /* data=*/13, /* cs=*/15, /* dc=*/5); //建立OLED对象,14,13,15,5 为各自对应的 GPIO 引脚编号
OLED 相关参数需要自行去询问厂商或查看原理图
就比如我这款 OLED 参数可以从原理图中看出来:
例程
使用 U8g2 例程 U8g2Logo,不过有些要稍作修改。
这个例程里给了很多种 OLED 型号的声明,根据自己的 OLED 型号和需求声明正确的参数,把注释取消掉即可。
注意只能有一个声明。
原代码在例程:
修改后的代码:
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
// Please UNCOMMENT one of the contructor lines below
// U8g2 Contructor List (Picture Loop Page Buffer)
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
//U8G2_NULL u8g2(U8G2_R0); // null device, a 8x8 pixel display which does nothing
//U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 12, /* dc=*/ 4, /* reset=*/ 6); // Arduboy (Production, Kickstarter Edition)
//U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_3W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_128X64_ALT0_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // same as the NONAME variant, but may solve the "every 2nd line skipped" problem
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 16, /* data=*/ 17, /* reset=*/ U8X8_PIN_NONE); // ESP32 Thing, pure SW emulated I2C
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17); // ESP32 Thing, HW I2C with pin remapping
//U8G2_SSD1306_128X64_NONAME_1_6800 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_8080 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_VCOMH0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but maximizes setContrast() range
//U8G2_SSD1306_128X64_ALT0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but may solve the "every 2nd line skipped" problem
//U8G2_SH1106_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SH1106_128X64_VCOMH0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but maximizes setContrast() range
//U8G2_SH1106_128X64_WINSTAR_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but uses updated SH1106 init sequence
//U8G2_SH1106_128X32_VISIONOX_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SH1106_128X32_VISIONOX_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1106_72X40_WISE_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1107_64X128_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1107_128X128_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1107_128X128_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ 8);
//U8G2_SH1107_PIMORONI_128X128_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ 8);
//U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SH1107_SEEED_128X128_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SH1107_SEEED_96X96_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1108_160X160_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1122_256X64_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // Enable U8G2_16BIT in u8g2.h
//U8G2_SSD1306_128X32_UNIVISION_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 21, /* data=*/ 20, /* reset=*/ U8X8_PIN_NONE); // Adafruit Feather M0 Basic Proto + FeatherWing OLED
//U8G2_SSD1306_128X32_UNIVISION_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // Adafruit Feather ESP8266/32u4 Boards + FeatherWing OLED
//U8G2_SSD1306_128X32_UNIVISION_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED
//U8G2_SSD1306_128X32_UNIVISION_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA); // pin remapping with ESP8266 HW I2C
//U8G2_SSD1306_128X32_WINSTAR_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA); // pin remapping with ESP8266 HW I2C
//U8G2_SSD1306_64X48_ER_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // EastRising 0.66" OLED breakout board, Uno: A4=SDA, A5=SCL, 5V powered
//U8G2_SSD1306_48X64_WINSTAR_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_64X32_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_64X32_1F_1_HW_