底层控制器指令 (最核心的命令)
这是直接驱动OLED屏幕工作的“机器语言”,绝大多数OLED屏幕都基于几种常见的控制器,其中最流行的是 SSD1306(单色,I2C/SPI接口)和 SH1106(兼容SSD1306指令,分辨率更高),这里我们以最常用的 SSD1306 (I2C接口) 为例。

这些命令通常通过I2C或SPI总线发送,前面会跟着一个控制字节(对于I2C,0x00表示写入命令,0x40表示写入数据)。
初始化命令序列
要让一个OLED屏幕工作,首先要发送一整套初始化命令,这是一个典型的SSD1306初始化流程:
// 典型的SSD1306初始化命令列表 (通过I2C发送) // 每个命令前面都要加上 0x00 (I2C控制字节,表示写命令) // 1. 关闭显示 0x00, 0xAE // 2. 设置时钟分频率/振荡器频率 0x00, 0xD5, 0x80, 0x80 // [D5] Set Display Clock Divide Ratio/Oscillator Frequency, [80] Recommended Value // 3. 设置多路复用率 0x00, 0xA8, 0x3F // [A8] Set Multiplex Ratio, [3F] For 128x64, 0x7F for 128x32 // 4. 设置显示偏移 0x00, 0xD3, 0x00 // [D3] Set Display Offset, [00] No offset // 5. 设置起始行 (通常从0开始) 0x00, 0x40 // [40] Set Display Start Line // 6. 电荷泵设置 0x00, 0x8D, 0x14 // [8D] Set Charge Pump, [14] Enable // 7. 设置内存地址模式 (水平地址模式最常用) 0x00, 0x20, 0x00 // [20] Set Memory Addressing Mode, [00] Horizontal Addressing Mode // 8. 设置列地址范围 0x00, 0x21, 0x00, 0x7F // [21] Set Column Address, [00] Start Column (0), [7F] End Column (127) // 9. 设置页地址范围 0x00, 0x22, 0x00, 0x07 // [22] Set Page Address, [00] Start Page (0), [07] End Page (7 for 128x64) // 10. 设置显示开启/对比度 0x00, 0xA1, // [A1] Set Segment Re-map (column 127 is mapped to SEG0) 0x00, 0xC8, // [C8] Set COM Output Scan Direction (remap, COM63 to COM0) 0x00, 0xA6, // [A6] Set Normal Display (not inverted) 0x00, 0xA8, 0x3F, // [A8] Set MUX Ratio 0x00, 0xD9, 0xF1, // [D9] Set Pre-charge Period 0x00, 0xDB, 0x40, // [DB] Set VCOMH Deselect Level // 11. 开启显示 0x00, 0xAF
解读:
0xAE:关闭显示(在初始化完成前通常关闭,最后再开启)。0xA8:设置多路复用率,决定了屏幕有多少行像素。0x3F代表64行(适用于128x64屏幕)。0x20:设置内存寻址模式。0x00是水平寻址,这是最高效的模式,通常按行(页)填充数据。0x21和0x22:最关键的两个命令,它们定义了你接下来要写入数据的区域(窗口)。0x21设置列地址(宽度),0x22设置页地址(高度),对于128x64屏幕,有128列和8页(每页8像素高)。0xAF:开启显示。
常用功能命令
| 十六进制命令 | 功能描述 |
|---|---|
0xAE |
关闭显示 |
0xAF |
开启显示 |
0xA4 |
恢复显示内容(之前的内容会重新出现) |
0xA5 |
整屏点亮(所有像素为亮) |
0xA6 |
设置正常显示(默认,0为灭,1为亮) |
0xA7 |
设置反显显示(0为亮,1为灭) |
0xB0 ~ 0xB7 |
设置页地址(选择当前操作的页) |
0x00 ~ 0x0F |
设置列地址低4位 |
0x10 ~ 0x1F |
设置列地址高4位 |
0x81 |
对比度设置,后跟一个字节(0-255) |
0xD9, 0xF1 |
设置预充电周期(通常使用推荐值) |
0xDB, 0x40 |
设置VCOMH电压取消级别(通常使用推荐值) |
图形库函数 (开发者最常用的“命令”)
直接发送底层命令非常繁琐,开发者通常会使用封装好的图形库,如 U8g2、Adafruit SSD1306、LiquidCrystal_I2C (用于字符屏) 等,这些库将底层命令封装成了简单的函数。

以流行的 U8g2库 为例,这些就是你实际在代码中调用的“命令”。
初始化
#include <U8g2lib.h>
// 定义OLED连接方式 (I2C, SSD1306, 128x64)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void setup() {
// 初始化OLED
u8g2.begin();
}
显示控制命令
// 清空屏幕 (填充黑色) u8g2.clearDisplay(); // 将缓冲区内容发送到屏幕并更新 u8g2.sendBuffer(); // 设置翻转显示 (0x00正常, 0x01旋转180度) u8g2.setRot180(); // 或 u8g2.setFlipMode(1); // 设置对比度 (0-255) u8g2.setContrast(200);
绘图命令
这些命令都在一个内存缓冲区中操作,最后调用 sendBuffer() 一并显示。
// 1. 绘制基本图形 // 画点 (x, y, 是否点亮) u8g2.drawPixel(10, 20, 1); // 画线 (x1, y1, x2, y2) u8g2.drawLine(0, 0, 127, 63); // 画框 (x, y, width, height) u8g2.drawFrame(10, 10, 50, 30); // 画实心框 (x, y, width, height) u8g2.drawBox(70, 10, 50, 30); // 画圆 (x, y, radius) u8g2.drawCircle(64, 32, 20); // 画实心圆 (x, y, radius) u8g2.fillCircle(64, 32, 15); // 2. 绘制文本 // 设置字体 (U8g2提供了大量字体) u8g2.setFont(u8g2_font_ncenB14_tr); // 设置14号字体 // 在指定位置打印字符串 (x, y, "text") u8g2.drawStr(0, 20, "Hello"); // 打印数字 (需要先将数字转为字符串) char buf[10]; sprintf(buf, "%d", 12345); u8g2.drawStr(0, 40, buf); // 更高效的打印数字方法 u8g2.drawStr(0, 60, u8x8_u8toa(123, 3)); // 打印123,至少占3个字符宽度
硬件接口命令 (如何发送命令)
无论底层命令还是库函数,最终都要通过物理接口发送给OLED。
I2C 接口 (最常见)
- 原理: 两根线:
SDA(数据线) 和SCL(时钟线)。 - 命令发送: 发送一个控制字节,再发送命令字节。
- 控制字节:
0x00(表示写入命令) 或0x40(表示写入数据)。 - 发送
0xAE(关闭显示) 命令:- I2C开始信号
- 发送OLED的I2C地址 (通常是
0x3C或0x3D) - 发送控制字节
0x00 - 发送命令字节
0xAE - I2C停止信号
- 控制字节:
- 数据发送: 发送一个控制字节,再发送一个或多个数据字节。
- 填充屏幕第一页的数据:
- 设置显示窗口 (通过底层命令
0x21,0x22... 设为全屏) - I2C开始信号
- 发送OLED的I2C地址
- 发送控制字节
0x40 - 连续发送128个字节的数据 (代表第一页128个像素的亮灭)
- I2C停止信号
- 设置显示窗口 (通过底层命令
- 填充屏幕第一页的数据:
SPI 接口 (速度更快,需要更多引脚)
- 原理: 通常需要4根线:
SCLK(时钟),SDIN(MOSI, 数据输入),DC(数据/命令选择),CS(片选)。 - 命令/数据选择: 通过
DC引脚的电平来区分当前发送的是命令还是数据。DC = LOW: 接下来发送的是命令。DC = HIGH: 接下来发送的是数据。
- 发送过程:
- 发送命令:拉低
CS-> 拉低DC-> 通过SDIN发送命令字节 -> 拉高CS。 - 发送数据:拉低
CS-> 拉高DC-> 通过SDIN连续发送数据字节 -> 拉高CS。
- 发送命令:拉低
| 层面 | 命令类型 | 描述 | 示例 |
|---|---|---|---|
| 底层 | 控制器指令 | 直接与OLED芯片通信的十六进制代码,最原始。 | 0xAE (关闭), 0xAF (开启), 0x21 (设置列地址) |
| 应用层 | 图形库函数 | 封装了底层指令的C/C++函数,开发者最常用。 | u8g2.clearDisplay(), u8g2.drawStr("Hello") |
| 物理层 | 接口信号 | 通过I2C或SPI协议传输命令和数据的具体电信号。 | I2C地址 0x3C, SPI的 DC 引脚电平 |
对于绝大多数开发者来说,你只需要了解和使用层面二(图形库函数)即可,只有在需要移植驱动、或者对性能有极致要求时,才需要深入研究层面一(底层指令)和层面三(硬件接口)。

