news 2026/8/30 23:18:25

OLED 显示屏——让 Arduino 拥有自己的“屏幕“

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OLED 显示屏——让 Arduino 拥有自己的“屏幕“

前面我们学了舵机、超声波、红外遥控,Arduino 已经能"动"、能"看"、能"遥控"了。但有个问题一直没解决——所有数据只能靠串口监视器看,你得连电脑才能知道 Arduino 在干什么。

今天这篇,我们要给 Arduino 装上一块OLED 显示屏,让它能独立显示文字、数字、图形,彻底摆脱电脑的束缚。

学完这篇,你会完成三个项目:

  • 文字显示:在 OLED 上显示自定义文字和实时数据
  • 图形绘制:画线、画圆、画矩形,制作简易仪表盘
  • 综合项目:智能测距仪:超声波测距 + OLED 实时显示,做成一个独立的小设备

一、OLED 显示屏是什么?

OLED(有机发光二极管)是一种自发光显示技术,和 LCD 不同,它不需要背光,每个像素自己发光。

OLED 的优势
  • 自发光:黑色区域完全不亮,对比度极高
  • 超薄:模块非常薄,适合嵌入各种项目
  • 低功耗:只点亮需要的像素,省电
  • 响应快:刷新速度快,适合动态显示
常见规格

Arduino 最常用的 OLED 模块是0.96 英寸 128×64 像素,有蓝色、白色、双色(上黄下蓝)等颜色可选。


二、通信方式:I2C

我们使用的 OLED 模块通过I2C 协议与 Arduino 通信,只需要 4 根线:

引脚接到作用
VCC5V(或 3.3V)供电
GNDGND接地
SCLA5I2C 时钟线
SDAA4I2C 数据线

I2C 是一种"总线"协议,多个设备可以共用 SCL 和 SDA 两根线。每个设备有自己的地址,Arduino 通过地址来区分它们。

查找 I2C 地址

OLED 模块的 I2C 地址通常是0x3C0x3D。如果不确定,可以用 I2C 扫描程序查找:

#include <Wire.h> void setup() { Serial.begin(9600); Wire.begin(); Serial.println("=== I2C 地址扫描 ==="); for (byte address = 1; address < 127; address++) { Wire.beginTransmission(address); if (Wire.endTransmission() == 0) { Serial.print("找到设备,地址: 0x"); Serial.println(address, HEX); } } Serial.println("扫描完成"); } void loop() {}

上传后打开串口监视器,它会列出所有连接在 I2C 总线上的设备地址。


三、安装必要的库

需要安装两个库:

  1. Adafruit SSD1306:OLED 驱动库
  2. Adafruit GFX Library:图形绘制库

安装步骤:

  1. 菜单工具 → 管理库
  2. 搜索Adafruit SSD1306,安装
  3. 搜索Adafruit GFX Library,安装

四、硬件清单

元件数量作用
Arduino Uno1块主控板
面包板1块搭建电路
0.96寸 OLED(I2C)1个显示屏
HC-SR04 超声波模块1个综合项目测距
杜邦线若干连接元件

五、电路接线

OLED 接线
  • VCC→ 接 5V
  • GND→ 接 GND
  • SCL→ 接 Arduino 的A5
  • SDA→ 接 Arduino 的A4
HC-SR04 接线(综合项目用)
  • VCC→ 接 5V
  • GND→ 接 GND
  • Trig→ 接 Arduino 的D9
  • Echo→ 接 Arduino 的D10

六、实验一:显示文字

在 OLED 上显示"Hello, Arduino!"和实时更新的计数器。

#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> // 屏幕参数 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 // 没有复位引脚,设为 -1 // 创建显示对象 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); int counter = 0; void setup() { Serial.begin(9600); // 初始化 OLED if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println("OLED 初始化失败!"); for (;;); // 初始化失败,停在这里 } Serial.println("OLED 初始化成功"); // 清屏 display.clearDisplay(); // 设置文字大小(1~5,数字越大字越大) display.setTextSize(1); // 设置文字颜色(SSD1306_WHITE 表示点亮像素) display.setTextColor(SSD1306_WHITE); // 设置光标位置(x, y) display.setCursor(0, 0); // 输出文字 display.println("Hello, Arduino!"); display.println("----------------"); display.println("OLED 显示测试"); // 将缓冲区内容刷新到屏幕 display.display(); } void loop() { // 清屏 display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.println("Counter:"); display.setTextSize(3); display.setCursor(20, 35); display.println(counter); // 刷新显示 display.display(); counter++; delay(500); }
代码解读
  • display.begin(SSD1306_SWITCHCAPVCC, 0x3C):初始化 OLED,参数是 I2C 地址
  • display.clearDisplay():清空屏幕(只是清空缓冲区,还没显示)
  • display.setTextSize(n):设置文字大小,1 是最小,数字越大字越大
  • display.setCursor(x, y):设置下一个文字的起始位置
  • display.println():写入文字到缓冲区
  • display.display():把缓冲区的内容真正刷新到屏幕上

注意:所有display.println()只是写入缓冲区,必须调用display.display()才会在屏幕上显示。这样设计是为了提高刷新效率——你可以一次性准备好所有内容,再一次性刷新。


七、实验二:图形绘制

OLED 不仅能显示文字,还能画各种图形。我们用 Adafruit GFX 库提供的绘图函数来画。

#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); display.clearDisplay(); // 画矩形边框 display.drawRect(0, 0, 128, 64, SSD1306_WHITE); // 画填充矩形 display.fillRect(5, 5, 40, 20, SSD1306_WHITE); // 画圆形 display.drawCircle(90, 32, 20, SSD1306_WHITE); // 画填充圆形 display.fillCircle(45, 45, 12, SSD1306_WHITE); // 画直线 display.drawLine(65, 45, 120, 45, SSD1306_WHITE); // 画三角形 display.drawTriangle(70, 55, 85, 45, 100, 55, SSD1306_WHITE); // 显示文字 display.setTextSize(1); display.setCursor(8, 8); display.setTextColor(SSD1306_BLACK); // 在白色背景上用黑色字 display.println("GFX"); display.setTextColor(SSD1306_WHITE); display.setCursor(70, 58); display.println("Shapes"); display.display(); } void loop() {}
常用绘图函数
函数作用
drawPixel(x, y, color)画一个点
drawLine(x1, y1, x2, y2, color)画直线
drawRect(x, y, w, h, color)画矩形边框
fillRect(x, y, w, h, color)画填充矩形
drawCircle(x, y, r, color)画圆形边框
fillCircle(x, y, r, color)画填充圆形
drawTriangle(x1,y1, x2,y2, x3,y3, color)画三角形
drawRoundRect(x, y, w, h, radius, color)画圆角矩形

坐标系:左上角是 (0, 0),x 向右增大,y 向下增大。屏幕右下角是 (127, 63)。


八、综合项目:智能测距仪

把超声波和 OLED 结合起来,做一个独立的测距仪——不需要连电脑,开机就能实时显示距离。

#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); const int trigPin = 9; const int echoPin = 10; void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); // 初始化 OLED display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // 开机画面 display.setTextSize(2); display.setCursor(10, 10); display.println("Smart"); display.setCursor(10, 35); display.println("Ranger"); display.display(); delay(1500); } void loop() { // 测量距离 float distance = measureDistance(); // 清屏 display.clearDisplay(); // 画边框 display.drawRect(0, 0, 128, 64, SSD1306_WHITE); // 标题 display.setTextSize(1); display.setCursor(30, 5); display.println("Distance Meter"); // 分隔线 display.drawLine(0, 16, 128, 16, SSD1306_WHITE); // 显示距离(大字体) display.setTextSize(3); display.setCursor(10, 25); display.print(distance, 1); // 保留1位小数 // 单位 display.setTextSize(2); display.setCursor(95, 30); display.print("cm"); // 状态指示 display.setTextSize(1); display.setCursor(5, 55); if (distance < 20) { display.println("[!!!] DANGER"); } else if (distance < 50) { display.println("[!!] WARNING"); } else if (distance < 100) { display.println("[!] CAUTION"); } else { display.println("[OK] SAFE"); } // 刷新显示 display.display(); delay(200); } float measureDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH, 30000); if (duration == 0) return 999.9; // 超时返回 999.9 return duration / 58.0; }
效果
  • 开机:显示 "Smart Ranger" 启动画面,1.5 秒后进入测距模式
  • 测距模式:实时显示距离数值(大字体),下方显示安全状态
  • 状态判断
    • < 20cm:显示DANGER
    • 20~50cm:显示WARNING
    • 50~100cm:显示CAUTION
    • > 100cm:显示SAFE

这就是一个完整的独立设备了——不需要电脑,不需要串口,开机即用。


九、OLED 显示技巧

自定义大数字

默认字体最大只有 5 号,如果想要更大的数字,可以手动绘制像素点阵,或者使用 U8g2 库(支持更多字体)。

显示中文

Adafruit SSD1306 默认不支持中文。要显示中文,需要:

  1. 准备中文字库(取模工具生成)
  2. 将字库数据存入 Arduino 的 Flash 存储
  3. display.drawBitmap()绘制

中文显示比较复杂,因为 Arduino Uno 的 Flash 空间有限(32KB),放不下完整的中文字库。如果需要中文显示,建议使用 U8g2 库,它内置了多种中文字体。

动态刷新技巧

如果整个屏幕都刷新,会有闪烁感。可以只刷新变化的部分:

// 只清除数字区域,不重绘边框和标题 display.fillRect(10, 25, 80, 25, SSD1306_BLACK); display.setTextSize(3); display.setCursor(10, 25); display.print(distance, 1); display.display();

十、常见问题排查

Q:OLED 什么都不显示?

  • 检查 I2C 地址是否正确(用扫描程序确认)
  • 检查 SCL 接 A5,SDA 接 A4
  • 确认display.begin()没有返回 false

Q:显示内容模糊或有残影?

  • 每次刷新前先调用display.clearDisplay()
  • 如果只更新部分内容,确保清除区域覆盖了旧内容

Q:屏幕亮度太低?

可以在setup()中调整对比度:

display.ssd1306_command(SSD1306_SETCONTRAST); display.ssd1306_command(255); // 0~255,255 最亮

Q:刷新速度太慢?

减少display.display()的调用频率,或者只刷新变化的区域。


十一、本篇小结

回顾一下今天学到的核心知识:

  • OLED 原理:自发光显示,高对比度,低功耗
  • I2C 通信:只需 SCL + SDA 两根线,通过地址区分设备
  • Adafruit SSD1306 库:初始化、清屏、设置光标、输出文字、刷新显示
  • Adafruit GFX 库:画点、线、矩形、圆形、三角形等图形
  • 缓冲区机制:先写入缓冲区,再一次性刷新到屏幕
  • 综合项目:超声波 + OLED = 独立测距仪

OLED 显示屏让 Arduino 项目从"只能看串口"升级为"自带屏幕的独立设备"。下一篇,我们学习温湿度传感器 DHT11——让 Arduino 能够感知环境温度和湿度,做一个气象站。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 23:18:11

自动售货机NFC支付模块集成实战:从硬件选型到交易流程的工程实践

在自动售货机从“投币出货”向“无感支付”演进的过程中&#xff0c;NFC非接触支付正在成为智能售货机的标配功能。用户只需将手机或银行卡靠近设备&#xff0c;即可完成支付&#xff0c;全程无需扫码、无需输入密码。但NFC模块的集成涉及硬件选型、通信协议、安全认证等多个环…

作者头像 李华
网站建设 2026/8/30 23:12:44

ROS2 Humble机器人小车开发骨架:工程级可部署最小可行框架

简介&#xff1a;本资源是一套完整的基于ROS2的机器人小车开发项目&#xff0c;面向高校自动化、机器人工程、人工智能等专业的本科生开展毕业设计、课程设计或期末大作业实践。项目覆盖感知&#xff08;LIDAR/摄像头/红外&#xff09;、决策&#xff08;SLAM建图、导航规划&am…

作者头像 李华
网站建设 2026/8/30 23:11:04

LangGraph 节点触发机制通俗解读

LangGraph 节点触发机制通俗解读基于 LangGraph 1.2.9 源码&#xff0c;用白话解释“节点为什么会被触发”。节点触发机制 LangGraph 的调度模型并非“通道数据变化时即时触发回调/事件通知节点&#xff08;Push-based&#xff09;”&#xff0c;而是基于 BSP&#xff08;块同步…

作者头像 李华
网站建设 2026/8/30 23:09:26

工厂自动化现场调试实战:从串口到总线,通信链路排查全攻略

1. 方案的价值在调试中兑现&#xff1a;先把自动化系统的层次理清楚参加完工业峰会&#xff0c;拿到一堆工厂自动化解决方案资料&#xff0c;PPT里各种架构图、数据流图看着都很完整&#xff0c;厂商把设备层、控制层、信息层画得清清楚楚&#xff0c;但等你真正拿着这套方案去…

作者头像 李华
网站建设 2026/8/30 23:08:30

怕AIGC标红踩坑?2026年亲测15款免费降AI工具,附白嫖指南

熬了好几个大夜憋出来的论文&#xff0c;一测AI生成率直接爆表&#xff0c;这种欲哭无泪的感觉谁懂啊&#xff01;为了把AI率压到安全线内&#xff0c;我前前后后试了十几款工具&#xff0c;今天把亲测好用的整理出来——不管你是想找免费的试手方案&#xff0c;还是要能稳过审…

作者头像 李华
网站建设 2026/8/30 23:07:29

三款AI写作辅助软件横评:从选题到答辩怎么选才不踩坑?

写论文这事&#xff0c;最怕的不是写不出来&#xff0c;而是写得心里没底。 题目改了七八版还怕选重了&#xff0c;文献下载了两百篇越读越乱&#xff0c;参考文献格式调到崩溃&#xff0c;交稿前还得担心重复率和AIGC检测。今年开学季一到&#xff0c;又有一波人在搜“AI论文工…

作者头像 李华