Chapter 08 · Arduino 入门

LCD 与 OLED 显示

给项目加一块屏幕:1602 字符 LCD、I2C 转接省引脚、SSD1306 OLED 显示文字与图形。

课程进度67%

关键概念

1602 字符 LCD
最经典的字符液晶:2 行、每行 16 个字符,基于 HD44780 控制器。只能显示预置的字符/数字(以及少量自定义字符),不能画任意图形。有背光,价格便宜,适合显示温度、状态等文本。
并口 vs I2C 接法
原生 1602 是并口,需占用 6+ 个引脚(RS、EN、D4~D7)接线繁琐。市面多用焊了 PCF8574 I2C 转接板的版本,只需 SDA、SCL 两根数据线 + 电源,大幅省引脚,也是本章推荐接法。
I2C 总线
Inter-Integrated Circuit。只用两根线(SDA 数据、SCL 时钟)就能挂载多个设备的总线协议,每个设备有唯一地址。Uno 的 I2C 引脚固定在 A4(SDA)、A5(SCL)。第 10 章会深入讲原理,本章先会用。
I2C 地址
总线上每个设备的"门牌号"(7 位,如 0x27、0x3C)。主机靠地址找到目标设备通信。1602 I2C 板常见 0x27 或 0x3F,OLED 常见 0x3C。地址不对就点不亮,需用"I2C 扫描"程序探测实际地址。
OLED (SSD1306)
有机发光显示屏,自发光、对比度极高、省电。常见 0.96 寸 128×64 像素、SSD1306 驱动、I2C 接口。可逐像素点亮,能显示任意文字、图形、动画、进度条,比 1602 灵活得多,是现代创客项目的首选小屏。
LiquidCrystal_I2C 库
驱动 I2C 版 1602 的常用库。创建对象时传入地址、列数、行数,用 setCursor(列,行) 定位、print() 写字符、clear() 清屏。安装:库管理器搜 "LiquidCrystal I2C"。
U8g2 库
功能强大的单色显示库,支持几乎所有 OLED/LCD 型号,内置大量字体、图形函数。采用"页缓冲"绘制,省 RAM。相比 Adafruit_SSD1306(全帧缓冲、更吃 RAM 但 API 直观),U8g2 在 Uno 这种小内存芯片上更友好。
帧缓冲 (Frame Buffer)
先在内存里画好一整屏画面,再一次性刷到屏幕,避免闪烁。128×64 单色屏一帧需 128×64/8 = 1024 字节 RAM——占了 Uno 一半 SRAM!所以内存吃紧时 U8g2 的分页模式(每次只缓存一小条)更合适。

先做一个 I2C 地址扫描器

接好 I2C 设备后,第一步永远是扫地址——不知道地址就没法初始化库。这段代码是万能工具,值得收藏:

#include <Wire.h>   // Arduino 自带 I2C 库

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Serial.println("扫描 I2C 设备...");
}

void loop() {
  int count = 0;
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    // endTransmission 返回 0 表示该地址有设备应答
    if (Wire.endTransmission() == 0) {
      Serial.print("发现设备,地址 0x");
      Serial.println(addr, HEX);   // 以十六进制打印
      count++;
    }
  }
  if (count == 0) Serial.println("没找到设备,检查接线!");
  delay(3000);
}
I2C 设备统一接线(SDA/SCL 并联) Arduino 1602 I2C 板 / OLED ───────── ────────────────── 5V(或3.3V) ──────→ VCC GND ──────→ GND A4 (SDA) ──────→ SDA ← 数据线 A5 (SCL) ──────→ SCL ← 时钟线 多个 I2C 设备可【并联】共用这两根线(只要地址不冲突): A4 ─┬─ 设备1 SDA ─┬─ 设备2 SDA A5 ─┴─ 设备1 SCL ─┴─ 设备2 SCL

驱动 1602 LCD(I2C 版)

装 "LiquidCrystal I2C" 库,扫到地址(假设 0x27)后:

#include <LiquidCrystal_I2C.h>

// 参数:地址, 列数, 行数
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();          // 初始化
  lcd.backlight();     // 打开背光

  lcd.setCursor(0, 0);   // 第 0 列,第 0 行
  lcd.print("Hello Arduino");

  lcd.setCursor(0, 1);   // 第 0 列,第 1 行
  lcd.print("gufacode.com");
}

void loop() {
  // 在第二行动态显示秒数
  lcd.setCursor(0, 1);
  lcd.print("Time: ");
  lcd.print(millis() / 1000);
  lcd.print("s   ");   // 末尾空格覆盖旧字符
  delay(1000);
}
刷新数字的小技巧

LCD 不会自动擦除旧内容。数字从 100 变成 99 时,若不处理,屏上会显示 "99" 后面残留一个 "0" 变成 "990"。解决法:数字后补几个空格覆盖(如上例的 "s "),或用 lcd.clear() 整屏清除(但 clear 较慢会闪)。看不清字请调板上的蓝色电位器改对比度。

驱动 SSD1306 OLED(U8g2 库)

OLED 能显示图形。装 "U8g2" 库,用它显示文字和一个进度条:

#include <U8g2lib.h>
#include <Wire.h>

// 128x64 I2C OLED,用页缓冲模式(省 RAM)
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);

void setup() {
  u8g2.begin();
}

void loop() {
  int progress = (millis() / 50) % 100;   // 0~99 模拟进度

  // 页缓冲绘制:firstPage/nextPage 循环
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB10_tr);   // 选字体
    u8g2.drawStr(0, 15, "Arduino OLED"); // (x,y,文字)

    // 画进度条边框
    u8g2.drawFrame(0, 30, 128, 12);
    // 画进度条填充
    u8g2.drawBox(2, 32, progress * 124 / 100, 8);

    // 画一个圆
    u8g2.drawCircle(110, 55, 6);
  } while (u8g2.nextPage());   // 逐页刷到屏幕

  delay(30);
}
firstPage/nextPage 是什么套路

U8g2 的分页模式:屏幕被切成几条"页",库每次只在 RAM 里缓存一页、画完刷出去,如此循环覆盖整屏。所以你的绘制代码要放在 do { ... } while(u8g2.nextPage()) 里,它会被自动重复执行多次(每页一次)。好处是只需极少 RAM,非常适合 Uno。

1602 LCD vs SSD1306 OLED

特性1602 LCDSSD1306 OLED
显示内容仅字符(2×16)任意像素/图形/文字
分辨率16×2 字符128×64 像素
接口I2C(转接)或并口I2C 或 SPI
可视性需背光,对比度一般自发光,对比度极高
RAM 占用极小较大(帧缓冲)
价格/场景便宜,纯文本稍贵,图形界面
OLED 点不亮的排查顺序

① 先跑 I2C 扫描确认地址(OLED 常见 0x3C,也有 0x3D),库里若默认地址不符要指定;② 确认 VCC 电压(多数 OLED 3.3V/5V 兼容,但有的只支持 3.3V);③ SDA/SCL 别接反;④ 选对库中的型号宏(NONAME/常见即 SSD1306 128X64);⑤ Uno 用 U8g2 而非全帧缓冲库以防 RAM 不足死机。

本章小结

给项目加屏幕有两大选择。1602 字符 LCD:2 行×16 字符,只能显示文本,推荐买 I2C 转接版(PCF8574),只需 SDA/SCL 两线;用 LiquidCrystal_I2C 库,init()+backlight() 初始化、setCursor(列,行) 定位、print() 写字,刷新数字时末尾补空格覆盖残留、板上电位器调对比度。SSD1306 OLED:128×64 像素、自发光、可画任意图形,用 U8g2 库(分页模式省 RAM,绘制代码放在 firstPage/do...while(nextPage()) 里)。二者都走 I2C 总线,Uno 的 I2C 固定在 A4(SDA)/A5(SCL),多设备可并联(地址不冲突即可)。上手任何 I2C 设备的第一步都是跑地址扫描程序确认门牌号(1602 常见 0x27/0x3F,OLED 常见 0x3C)——地址不对是点不亮的头号原因。Uno 内存小,OLED 优先用 U8g2 而非全帧缓冲库。

⚒️ 配套开发者工具箱 · 17 款免费在线工具