软件程序设计
如果想要使用 Arduino 控制 SSD1306 驱动的 OLED 屏幕,有以下两种第三方库可以使用:
Adafruit_SSD1306库
:专门针对 SSD1306 驱动 OLED 屏幕的显示图形库;U8G2库
:目前 Arduino平台上使用最广泛的 OLED 库。
本篇文章主要学习调用 Adafruit_SSD1306库
, U8G2库
,使用软硬件SPI协议驱动7针脚OLED显示屏,以及软硬件IIC协议驱动4针脚OLED显示屏。
Adafruit_SSD1306 控制 OLED 屏幕
想要使用 Adafruit_SSD1306
,还需要安装 Adafruit_GFX
第三方库。Arduino 的 Adafruit_GFX库
为我们所有的 LCD 和 OLED 显示器提供了通用语法和图形功能集,也就是说这是一个通用图形库,并不针对特定的显示器型号。
Adafruit_GFX
定义了一系列的绘画方法(线,矩形,圆等等),属于基础类,并且最重要的一点,drawPixel 方法由子类来实现;Adafruit_SSD1306
定义了一系列跟 SSD1306 有关的方法,并且重写了 drawPixel 方法,属于扩展类。
一、 SPI 协议驱动 OLED 液晶屏幕
1. 软件SPI驱动OLED
a. 硬件电路搭建
引脚连接 | ESP32 | OLED |
---|---|---|
1 | GND | GND |
2 | VCC | VCC |
3 | D18(自定义) | SCK(SCL) |
4 | D13(自定义) | SDA(MOSI) |
5 | D15 | RES |
6 | D2 | DC |
7 | D4 | CS |
b. 软件程序
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define WIDTH 128 // OLED display width, in pixels
#define HEIGHT 64 // OLED display height, in pixels
// 软件 SPI 总线
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_SCK 18
#define OLED_SDA 13
#define OLED_RES 15
#define OLED_DC 2
#define OLED_CS 4
// 构造对象
Adafruit_SSD1306 OLED(WIDTH, HEIGHT, OLED_SDA, OLED_SCK, OLED_DC, OLED_RES, OLED_CS);
void setup() {
// OLED初始化
OLED.begin();
// OLED清除显示
OLED.clearDisplay();
// 设置光标位置
OLED.setCursor(1, 1);
// 设置文本颜色
OLED.setTextColor(SSD1306_WHITE);
// 设置字体大小
OLED.setTextSize(2);
// 显示字符
OLED.println("HelloWorld");
// 显示内容
OLED.display();
}
void loop() {
// put your main code here, to run repeatedly:
}
c. 显示结果
2. 硬件SPI驱动OLED
a. 硬件电路搭建
引脚连接 | ESP32 | OLED |
---|---|---|
1 | GND | GND |
2 | VCC | VCC |
3 | D18 | SCK(SCL) |
4 | D23 | SDA(MOSI) |
5 | D15 | RES |
6 | D2 | DC |
7 | D4 | CS |
b. 软件程序
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define WIDTH 128
#define HEIGHT 64
#define OLED_DC 2
#define OLED_CS 4
#define OLED_RESET 15
Adafruit_SSD1306 OLED(WIDTH, HEIGHT, &SPI, OLED_DC, OLED_RESET, OLED_CS);
void setup() {
// OLED初始化
OLED.begin();
// OLED清除显示
OLED.clearDisplay();
// 设置光标位置
OLED.setCursor(1, 1);
// 设置文本颜色
OLED.setTextColor(SSD1306_WHITE);
// 设置字体大小
OLED.setTextSize(2);
// 显示字符
OLED.println("HelloWorld");
// 显示内容
OLED.display();
}
void loop() {
// put your main code here, to run repeatedly:
}
c. 显示结果
注:硬件SPI驱动OLED时,使用硬件SPI默认为ESP32的VSPI,使用到的引脚为
GPIO18(VSPICLK)
和GPIO23(VSPI MOSI)
,如果想使用HSPI的GPIO14(HSPI CLK)
和GPIO13(HSPIMOSI)
驱动OLED需要修改SPI.cpp
文件的程序末尾,将代码第348行括号中的VSPI改为HSPI即可。
修改之后的显示结果为:
关于ESP的硬件SPI、HSPI和VSPI的区别:
ESP32的HSPI和VSPI区别 - 盛世芳华 - 博客园 (cnblogs.com)
二、 IIC 协议驱动 OLED 液晶屏幕
硬件IIC驱动OLED
a. 硬件电路搭建
引脚连接 | ESP32 | OLED |
---|---|---|
1 | GND | GND |
2 | VCC | VCC |
3 | D22 | SCK(SCL) |
4 | D21 | SDA(MOSI) |
b. 软件程序
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
// 构造对象 连接到I2C(SDA、SCL引脚)的SSD1306声明
Adafruit_SSD1306 OLED(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
// OLED初始化
OLED.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
// OLED清除显示
OLED.clearDisplay();
// OLED设置光标位置
OLED.setCursor(1, 1);
// 设置字体颜色
OLED.setTextColor(SSD1306_WHITE);
// 显示字符串内容
OLED.println("Hello, world!");
OLED.display();
}
void loop() {
// put your main code here, to run repeatedly:
}
c. 显示结果
注:如果OLED 显示屏未显示任何内容:
- 检查 OLED 显示屏是否正确连接到 ESP32
- 仔细检查 OLED 显示屏 I2C 地址:OLED 连接到 ESP32 时,上传此代码并检查串行监视器中的 I2C 地址
如有必要,应更改以下行中的 OLED 地址。在我们的案例中,地址0x3C
。
通过运行 I2C 扫描仪草图来查找 OLED 地址,使用以下程序进行扫描即可。
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("\nI2C Scanner");
}
void loop() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
nDevices++;
}
else if (error==4) {
Serial.print("Unknow error at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
}
else {
Serial.println("done\n");
}
delay(5000);
}
查询到的IIC地址为0x3c
U8G2库控制OLED
为什么使用U8g2库?
- 平台支持性好,兼容多款开发板如ESP32、ESP8266、Arduino Uno等;
- 显示控制器支持性好,基本市面上的OLED都完美支持;
- API众多,特别支持了中文,支持了不同字体。
构造方法的名字有一定的规律
- U8G2_屏幕芯片_屏幕尺寸_缓存大小_总线
因为 U8G2
库兼容很多版本的驱动以及不同尺寸的 OLED,所以 U8G2 构造方法有很多,但是我们需要根据我们自己的 OLED 的型号,选择适合我们的构造方法。打开 U8g2lib.h
文件,找到构造器的位置。可以通过搜索:U8G2_SSD1306_128X64
进行查找相应的构造方法。
以下是7针脚SPI协议驱动OLED设备的构造器
U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI
U8G2_SSD1306_128X64_NONAME_2_4W_SW_SPI
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI
U8g2 支持以下两种绘制模式:
Full screen buffer mode,全屏缓存模式;
Page mode,分页模式;
本篇博客使用全屏缓存模式
实现OLED的驱动显示功能。
全屏缓存模式使用步骤:
- 构造对象,根据 OLED 的型号选择对应的构造器,构造器必须带
F
;- 初始化对象,使用
begin()
方法,清除缓冲区内容,使用u8g2.clearBuffer()
;- 绘制内容,使用绘制函数或者设置字体等;
- 发送缓冲区的内容到显示器
u8g2.sendBuffer()
。
一、SPI协议驱动OLED液晶屏幕
1. 软件SPI驱动OLED
a. 硬件电路搭建
b. 软件程序
#include <Arduino.h>
#include <U8g2lib.h>
#define OLED_SCK 18
#define OLED_SDA 13
#define OLED_RES 15
#define OLED_DC 2
#define OLED_CS 4
// 构造对象
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI OLED(U8G2_R0, OLED_SCK, OLED_SDA, OLED_CS, OLED_DC, OLED_RES); // ESP32 Thing, HW I2C with pin remapping
void setup() {
// 初始化OLED
OLED.begin();
// 开启中文字符集支持
OLED.enableUTF8Print();
// 设置字体
OLED.setFont(u8g2_font_wqy12_t_chinese2);
}
void loop() {
// 清除缓存区内容
OLED.clearBuffer();
// 绘制内容
OLED.setCursor(0, 10);
OLED.print("Hello, world!");
OLED.setCursor(0, 40);
OLED.print("你好,世界!");
// 发送缓存区内容到OLED
OLED.sendBuffer();
delay(1000);
}
c. 显示结果
1. 硬件SPI驱动OLED
a. 硬件电路搭建
b. 软件程序
#include <Arduino.h>
#include <U8g2lib.h>
#define OLED_RES 15
#define OLED_DC 2
#define OLED_CS 4
// 构造对象
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI OLED(U8G2_R0, OLED_CS, OLED_DC, OLED_RES); // ESP32 Thing, HW I2C with pin remapping
void setup() {
// 初始化OLED
OLED.begin();
// 开启中文字符集支持
OLED.enableUTF8Print();
// 设置字体
OLED.setFont(u8g2_font_wqy12_t_chinese2);
}
void loop() {
// 清除缓存区内容
OLED.clearBuffer();
// 绘制内容
OLED.setCursor(0, 10);
OLED.print("Hello, world!");
OLED.setCursor(0, 40);
OLED.print("你好,世界!");
// 发送缓存区内容到OLED
OLED.sendBuffer();
delay(1000);
}
c. 显示结果
二、IIC协议驱动OLED液晶屏幕
1. 软件IIC驱动OLED
a. 硬件电路搭建
引脚连接 | ESP32 | OLED |
---|---|---|
1 | GND | GND |
2 | VCC | VCC |
3 | D18(自定义) | SCK(SCL) |
4 | D5(自定义) | SDA(MOSI) |
b. 软件程序
#include <Arduino.h>
#include <U8g2lib.h>
// 自定义CLK和SDA引脚
#define OLED_CLK 18
#define OLED_SDA 5
// 构造对象
U8G2_SSD1306_128X64_NONAME_F_SW_I2C OLED(U8G2_R0, OLED_CLK, OLED_SDA, U8X8_PIN_NONE);
void setup() {
// 初始化OLED
OLED.begin();
// 开启中文字符集支持
OLED.enableUTF8Print();
// 设置字体
OLED.setFont(u8g2_font_wqy12_t_gb2312);
}
void loop() {
// 清除缓存区内容
OLED.clearBuffer();
// 绘制内容
OLED.setCursor(0, 10);
OLED.print("Hello, world!");
OLED.setCursor(0, 30);
OLED.print("你好,世界!");
// 发送缓存区内容到OLED
OLED.sendBuffer();
delay(1000);
}
c. 显示结果
2. 硬件IIC驱动OLED
a. 硬件电路搭建
b. 软件程序
#include <Arduino.h>
#include <U8g2lib.h>
// 构造对象
U8G2_SSD1306_128X64_NONAME_F_HW_I2C OLED(U8G2_R0);
void setup() {
// 初始化OLED
OLED.begin();
// 开启中文字符集支持
OLED.enableUTF8Print();
// 设置字体
OLED.setFont(u8g2_font_wqy12_t_gb2312);
}
void loop() {
// 清除缓存区内容
OLED.clearBuffer();
// 绘制内容
OLED.setCursor(0, 10);
OLED.print("Hello, world!");
OLED.setCursor(0, 30);
OLED.print("你好,世界!");
// 发送缓存区内容到OLED
OLED.sendBuffer();
delay(1000);
}
c. 显示结果
注:
- 在vscode中使用U8g2库驱动OLED显示中文时,标点符号应尽量用英文字符代替,防止库中没有相应的中文标点;
- 编译程序时注意vscode开发环境的编码方式,若选用GB2312编码方式,应切换到UTF-8(vscode切换编码方式后,会产生中文乱码现象,这时按下
ctrl + z
即可恢复文本正常, 且编码方式仍然保留)。
结语
掌握了ESP32驱动OLED基本显示功能之后,就可以拓展学习其他更多的显示效果啦,深入学习OLED显示功能的小伙伴可以参考以下网址。
本篇博客参考了以下资料: