显示设备
显示设备让 Arduino 能够直观地输出信息。本章将介绍 LCD、OLED 和数码管等常用显示设备的使用方法。
LCD1602 液晶显示屏
LCD1602 是最常用的字符型液晶显示屏,可以显示 2 行,每行 16 个字符。
硬件连接(I2C 方式)
使用 I2C 转接板可以大大简化接线:
LCD I2C VCC ── 5V
LCD I2C GND ── GND
LCD I2C SCL ── A5(Uno)
LCD I2C SDA ── A4(Uno)
安装库
项目 → 加载库 → 管理库 → 搜索 "LiquidCrystal I2C"
代码示例
#include <LiquidCrystal_I2C.h>
// 创建 LCD 对象,参数:I2C 地址(通常是 0x27 或 0x3F),列数,行数
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init(); // 初始化
lcd.backlight(); // 开启背光
// 显示文字
lcd.setCursor(0, 0); // 第 0 行,第 0 列
lcd.print("Hello, World!");
lcd.setCursor(0, 1); // 第 1 行,第 0 列
lcd.print("Arduino LCD");
}
void loop() {
// 闪烁效果
lcd.noBacklight();
delay(500);
lcd.backlight();
delay(500);
}
显示传感器数据
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(2, DHT22);
void setup() {
lcd.init();
lcd.backlight();
dht.begin();
lcd.setCursor(0, 0);
lcd.print("Temp: --.- C");
lcd.setCursor(0, 1);
lcd.print("Humi: --.- %");
}
void loop() {
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
if (!isnan(temp) && !isnan(humidity)) {
lcd.setCursor(6, 0);
lcd.print(temp, 1);
lcd.print(" C ");
lcd.setCursor(6, 1);
lcd.print(humidity, 1);
lcd.print(" % ");
}
delay(2000);
}
自定义字符
LCD1602 支持 8 个自定义字符:
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// 定义温度符号(5x8 像素)
byte tempChar[] = {
0b00100,
0b01010,
0b01010,
0b01110,
0b01110,
0b11111,
0b11111,
0b01110
};
// 定义湿度符号
byte humiChar[] = {
0b00100,
0b00100,
0b01110,
0b01110,
0b11111,
0b11111,
0b11111,
0b01110
};
void setup() {
lcd.init();
lcd.backlight();
// 创建自定义字符(0-7)
lcd.createChar(0, tempChar);
lcd.createChar(1, humiChar);
// 显示自定义字符
lcd.setCursor(0, 0);
lcd.write(byte(0)); // 显示温度符号
lcd.print(" 25.5 C");
lcd.setCursor(0, 1);
lcd.write(byte(1)); // 显示湿度符号
lcd.print(" 60.0 %");
}
void loop() {}
OLED 显示屏
OLED 显示屏具有自发光、高对比度、宽视角等优点,常见的有 0.96 寸和 1.3 寸两种尺寸。
硬件连接(I2C)
OLED VCC ── 3.3V 或 5V
OLED GND ── GND
OLED SCL ── A5(Uno)
OLED SDA ── A4(Uno)
安装库
项目 → 加载库 → 管理库 → 搜索 "Adafruit SSD1306"
代码示例
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 初始化失败"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("Hello, OLED!"));
display.println(F("Arduino 显示测试"));
display.display();
}
void loop() {}
显示图形
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}
void loop() {
display.clearDisplay();
// 画像素
display.drawPixel(10, 10, SSD1306_WHITE);
// 画线
display.drawLine(0, 0, 127, 63, SSD1306_WHITE);
// 画矩形
display.drawRect(20, 20, 40, 30, SSD1306_WHITE);
display.fillRect(70, 20, 40, 30, SSD1306_WHITE);
// 画圆
display.drawCircle(100, 50, 10, SSD1306_WHITE);
// 显示文字
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("OLED");
display.display();
delay(100);
}
动画效果
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int x = 0;
int y = 32;
int dx = 2;
int dy = 1;
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}
void loop() {
display.clearDisplay();
// 绘制跳动的球
display.fillCircle(x, y, 5, SSD1306_WHITE);
// 更新位置
x += dx;
y += dy;
// 边界检测
if (x <= 5 || x >= SCREEN_WIDTH - 5) dx = -dx;
if (y <= 5 || y >= SCREEN_HEIGHT - 5) dy = -dy;
display.display();
delay(20);
}
数码管显示
四位数码管(TM1637)
TM1637 驱动的四位数码管只需要两根数据线。
硬件连接:
TM1637 CLK ── D2
TM1637 DIO ── D3
TM1637 VCC ── 5V
TM1637 GND ── GND
安装库:搜索 "TM1637Display"
代码示例:
#include <TM1637Display.h>
const int CLK = 2;
const int DIO = 3;
TM1637Display display(CLK, DIO);
void setup() {
display.setBrightness(7); // 亮度 0-7
display.clear();
}
void loop() {
// 显示数字
display.showNumberDec(1234);
delay(1000);
// 显示带小数点
display.showNumberDecEx(1234, 0b01000000); // 12.34
delay(1000);
// 显示时间格式
display.showNumberDecEx(1530, 0b01000000, true); // 15:30
delay(1000);
// 倒计时
for (int i = 100; i >= 0; i--) {
display.showNumberDec(i);
delay(100);
}
}
74HC595 驱动数码管
使用移位寄存器节省 IO 引脚:
const int DATA_PIN = 11; // DS
const int LATCH_PIN = 12; // ST_CP
const int CLOCK_PIN = 13; // SH_CP
// 共阴极数码管段码(0-9)
const byte segmentPatterns[] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
// 位选引脚
const int digitPins[] = {2, 3, 4, 5};
void setup() {
pinMode(DATA_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH); // 共阴极,高电平关闭
}
}
void loop() {
// 显示 1234
int number = 1234;
displayNumber(number);
}
void displayNumber(int num) {
int digits[4];
digits[0] = num / 1000;
digits[1] = (num / 100) % 10;
digits[2] = (num / 10) % 10;
digits[3] = num % 10;
// 动态扫描显示
for (int i = 0; i < 4; i++) {
// 关闭所有位
for (int j = 0; j < 4; j++) {
digitalWrite(digitPins[j], HIGH);
}
// 发送段码
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, segmentPatterns[digits[i]]);
digitalWrite(LATCH_PIN, HIGH);
// 打开当前位
digitalWrite(digitPins[i], LOW);
delay(5); // 延时让眼睛能看到
}
}
综合示例:多功能仪表
整合多种显示设备的多功能仪表:
#include <LiquidCrystal_I2C.h>
#include <TM1637Display.h>
#include <DHT.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
TM1637Display tm1637(2, 3);
DHT dht(4, DHT22);
const int LDR_PIN = A0;
void setup() {
lcd.init();
lcd.backlight();
tm1637.setBrightness(7);
dht.begin();
lcd.setCursor(0, 0);
lcd.print("Multi-Display");
delay(1000);
lcd.clear();
}
void loop() {
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
int light = analogRead(LDR_PIN);
// LCD 显示温湿度
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(temp, 1);
lcd.print((char)223); // 度符号
lcd.print("C");
lcd.setCursor(9, 0);
lcd.print("H:");
lcd.print(humidity, 1);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Light:");
lcd.print(light);
lcd.print(" ");
// 数码管显示温度整数部分
int tempInt = (int)temp;
tm1637.showNumberDec(tempInt);
delay(2000);
}
显示设备对比
| 特性 | LCD1602 | OLED | 数码管 |
|---|---|---|---|
| 显示内容 | 字符 | 图形+文字 | 数字 |
| 背光 | 需要 | 自发光 | 自发光 |
| 可视角度 | 有限 | 宽 | 宽 |
| 功耗 | 中等 | 低 | 中等 |
| 价格 | 便宜 | 稍贵 | 便宜 |
| 适用场景 | 简单文字 | 复杂显示 | 数字显示 |
下一步
掌握了显示设备后,我们将学习如何存储数据,包括 EEPROM 和 SD 卡的使用。