模块熟悉
第 19 课:OLED 显示屏——把数字画出来
唯一会用 I²C 的模块,也是唯一能把信息"说出来"的模块
我是吴老师。这是「模块熟悉」单元的最后一节,也是这里面最"像样"的一个模块。
先说它最特别的地方:
前面所有的模块,要么只会"读",要么只会"亮/响/转"。
光敏只会告诉你亮不亮,按钮只会告诉你按没按,舵机只会转——它们都不会"说话"。 你想知道板子在想什么,只能打开电脑看串口监视器。一拔掉电脑,你就什么也看不见了。
OLED 是套件里唯一能把信息显示出来的模块。
这一下就不一样了。你的作品从"会闪的灯",变成了**"能说话的东西"**——它能告诉你现在几度、现在是几点、还剩多少电。
看视频时注意的三件事
这节课有视频,先看。视频里讲的是接线和跑通的全过程。
看的时候别光看热闹,盯这三件事:
第一,它是唯一一个用 I²C 的模块,所以它有两个信号线。
| 针脚 | 作用 |
|---|---|
| GND | 地 |
| VDD | 电源(就是正极,和 VCC 一个意思) |
SCK |
时钟线(就是 SCL) |
| SDA | 数据线 |
以前的模块,信号线要么就一根(OUT、AO、I/O),要么各用各的(超声波那两根 Trig/Echo 是它专用的)。而 OLED 这两根线是"总线"——以后所有 I²C 设备都并到这两根线上。 为什么这么设计?下一节讲。
第二,注意你板子上印的字。
教程里普遍写 VCC 和 SCL,但你手上这块印的是 VDD 和 SCK。
是同一个东西,接的位置完全一样。 别被字母差异唬住——这事儿第 4 课讲过,今天你第一次真的用上。
第三,注意显示的位置。
视频里我调了几次坐标,你会看到字写歪了、挤在一起。这都是正常的,多试两次就有手感了。
一、I²C:两根线挂一串设备
先回答"为什么它要两根线"。
以前那种接法是"一个设备一对线"。 你有 3 个传感器,就得占 3 根信号线,加上电源和地,一堆线缠在一起。
I²C 换了个思路:两根线,可以挂一长串设备。
打比方:I²C 就是大家一起用的一个对讲机频道。
- 一根线是时钟(
SCK/SCL)——相当于节拍,所有人跟着这个节奏说话 - 一根线是数据(
SDA)——相当于频道里说的话 - 每个设备有个地址——相当于门牌号 / 呼号
主控在数据里带上地址,发一句"0x3C,把这段话显示出来"。所有设备都听见了,但只有地址是 0x3C 的那个才应答,别的都装没听见。
(这玩意儿正式叫总线,你以后查资料会用到这个词。)
这是 I²C 最爽的地方:加一个新设备,不用再占新引脚。 只要把它并在那两根线上就行,
SCK和SDA是共用的。你后面做第 31 课(光敏 + 舵机 + OLED)的时候会发现:引脚不够用的时候,I²C 模块是最省心的那个。
还记得第 4 课我说"引脚要提前规划"吗?I²C 就是工程师为了解决这个麻烦想出来的办法。
但有个坑:地址冲突
如果两个设备的地址一样,它们会同时应答,谁也没法正常工作。
对讲机里两个人共用一个呼号,你喊一声,两个人一起开口——谁也听不清。 这就是地址冲突。
好消息:你套件里只有一个 I²C 模块,撞不上。
但以后你买第二个 I²C 传感器的时候,第一件事就是查它的地址。 有些模块背面有可以改地址的焊盘/跳线,买之前先看清楚。
你现在记着有这么回事就行。
二、接线:四根线
| OLED | 接到 |
|---|---|
| GND | GND |
| VDD | 3.3V |
SCK |
GPIO9(板子默认的 SCL) |
| SDA | GPIO8(板子默认的 SDA) |
注意最后两行:SCK 和 SDA 是一对,不能接反。 接反了屏幕不亮,但不会烧,换过来就行。
GPIO8/GPIO9是板子默认的 I²C 脚(图形化平台里也是这两个)。但第 4 课我提醒过:
GPIO8、GPIO9是启动时的特殊引脚,建议避开。 它们能用,你心里有个数就行——如果屏幕时不时不亮,或者板子偶尔启动不了,先怀疑这两个脚。换脚很简单:I²C 用哪两个 GPIO 是代码里指定的,不像有些接口是焊死的。换成
GPIO6/GPIO7,代码里同步改一句就行(下一节给代码)。
接之前还有个动作:先断电。 插好再上电,这是第 8 课就立下的规矩。
三、动手第一步:先显示一行字
代码路线要先确认库装好了。第 2 课你已经装过 Adafruit SSD1306 和 Adafruit GFX Library——当时我说"现在装好,省得上到这一课手忙脚乱",就是为今天准备的。
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 oled(128, 64, &Wire, -1); // 128×64 的屏
void setup() {
Wire.begin(8, 9); // 先 SDA,后 SCL(想换脚就改这里)
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 0x3C 是它的 I²C 地址
oled.clearDisplay();
oled.setTextSize(2); // 字的大小
oled.setTextColor(SSD1306_WHITE);
oled.setCursor(0, 0); // 从左上角开始写
oled.println("Hello OLED");
oled.display(); // 这一句才真的画到屏上
}
void loop() {
}烧进去。屏幕上应该出现一行 Hello OLED。
如果没亮,别慌,这是本课最正常的一件事,下面的"不亮怎么查"就是给你准备的。
display() 那一句,是新手最容易漏的
你注意到 oled.display() 了吗?前面画的、写的,一句都不落地。
因为那些 print、setCursor 都只是在"草稿纸"上画——画在板子的一块内存里,屏幕上一个像素都没变。只有 display() 这一句,才把草稿纸整个推到屏幕上。
忘了它,程序一点错都不报,屏幕就是不动。 这个坑坑过所有人,包括我。
屏不亮,按这个顺序查
先别改代码,按第 5 课那套顺序来:电 → 信号 → 代码。
- 供电:电压档,黑笔搭
GND、红笔点VDD,是不是 3.3V?没电,后面都免谈 - 接线:通断档,四根线一根一根量通断;顺便看看
SCK/SDA有没有接反 - 地址:这一步是 OLED 专属的——地址不对,屏幕就是死的。 大多数模块是
0x3C,但也有印0x3D的。搜一个 "I2C scanner"(I²C 扫描)的小程序烧进去,它会把你总线上所有能应答的地址打印出来。照它报的地址改代码。 - 代码:前面三步都排除了,再回头看代码
第 3 步那句话你记住:与其猜地址,不如让板子自己报出来。 这又是"先测,再猜"。
四、动手第二步:显示一个会变的数字
只会显示固定文字,那跟贴张纸条没区别。 我们来显示一个真正有用的东西——第 10 课那个电位器的读数。
void loop() {
int v = analogRead(0); // 读电位器(接在 GPIO0 上)
oled.clearDisplay(); // 先擦干净
oled.setCursor(0, 0);
oled.print("ADC: ");
oled.println(v);
oled.display(); // 再推上屏
delay(200);
}拧旋钮,屏上的数字跟着变。 到这一步,你的板子就真的"能说话"了。
那个 clearDisplay() 也别忘
它是这一节最值得体会的东西。
你把 clearDisplay() 那一行注释掉,再跑一遍——会看到数字叠在一起,一会儿就糊成一团黑。
为什么?因为屏幕不会自己"擦黑板"。你的每一次 print 都是"往上面画",新数字画在旧数字上面,两层叠一起就是一团。
所以画动态内容的标准套路是三步:
擦干净(
clearDisplay)→ 重新画(setCursor)→ 推上屏(display)
这三步你记牢,以后做第 30 课"坐姿提醒器"、第 34 课"联网天气站",全都要用。
五、动手第三步:坐标
最后玩一下位置。屏幕是 128 列 × 64 行(单位是像素),你要告诉它"从哪儿开始画":
oled.setCursor(0, 0); // 左上角
oled.setCursor(60, 30); // 偏中间
oled.setTextSize(1); // 字变小,能写更多setCursor(x, y)里的x是从左往右数的像素,y是从上往下数的像素setTextSize(2)就是字放大到 2 倍。放大了会占更多地方,所以字号变了,坐标也得跟着调
你多试几次,把字放到屏幕中间、右下角。 这个过程有点像在纸上写字之前先想好落笔的位置——试两次就有手感了。
y是从上往下数的,这个跟数学课上的坐标系是反的。别问为什么,屏幕行业一直就这么定。 你记住就行。
自测
答案与解析
I²C 是"大家共用两根线"的通信方式:时钟线提供节拍,数据线传输内容,每个设备有自己的门牌号(地址)。好处是省引脚——以后再加 I²C 设备,并到这两根线上就行。注意:它不是什么"内容多所以要两根",而且所有模块都要单独供电,这不是它特殊的地方。
VDD 和 SCK,但教程里写的是 VCC 和 SCL,怎么办?答案与解析
第 4 课那句话在这儿第一次真的用上:丝印是厂家随便印的,功能是芯片定死的。 VCC / VDD / 3V3 / VIN 一族都是正极,SCL / SCK 都是 I²C 时钟线(厂家沿用了 SPI 的丝印懒得改)。照着功能接,别照着字母接。
clearDisplay()?答案与解析
屏幕做的只是"画",它不会自己清空。 你不擦,新数字就画在旧数字上面,几轮下来糊成一团——这个现象你自己注释掉那行就能看到,比看解释印象深。 顺带说:烧屏这件事对 OLED 是真的,但那是"长时间显示同一个静止画面"造成的,跟这里每 0.2 秒刷新一次完全是两码事。
答题要点
答题要点应该包含:按第 5 课的**"电 → 信号 → 代码"**顺序,不要一上来就改代码。① 先查供电:万用表电压档,量 VDD 对 GND 是不是 3.3V;② 再查接线:通断档一根一根量,重点看 SCK 和 SDA 有没有接反;③ 然后查地址:跑一个 I²C 扫描程序,让板子把所有能应答的地址打出来,照着改代码里的 0x3C;④ 前三步都排除了,最后才回头看代码和库。核心观念:每一步都在"排除一种可能",而不是"试一个办法"。
拓展I²C 一共能挂多少个设备?为什么两个设备地址一样就会打架?
这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。
提示:搜"I2C 地址 7 位 112 个 保留地址"、"I2C 地址冲突 怎么办"。想一想:如果实在买不到两个地址不同的模块,还有别的办法吗?(提示:另一种叫 SPI 的总线,是"每个设备单独一根片选线",代价是什么?)
拓展屏幕上的一个字,是怎么被"画"出来的?
这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。
提示:搜"点阵字库 取模"、"OLED 显示原理 像素"。想一想:一个 16×16 的汉字,需要多少个小点来决定哪儿亮哪儿不亮?那这一整屏 128×64,又是多少个点?
本节你要动手做的事
- [ ] 认清丝印:
GNDVDDSCKSDA——VDD就是正极,SCK就是时钟,别被字母唬住 - [ ] 接好四根线(记得先断电再插):
VDD→3.3V,GND→GND,SCK/SDA→ 板子的两个 I²C 脚 - [ ] 先显示一行字:确认屏幕能亮。记得最后那句
display() - [ ] 不亮就用万用表查一遍:先量
VDD的电压,再量四根线的通断。先测,再猜 - [ ] 显示一个会变的数字:把第 10 课那个电位器接上,屏上显示它的读数
- [ ] 故意注释掉
clearDisplay():亲眼看看数字叠成一团糊的样子——这个现象比任何解释都记得住 - [ ] 调调位置和字号:
setCursor(x, y)、setTextSize(1/2/3),把字放到屏幕正中间
这个单元,你走完了
回头看看你这一路摸过的东西。
| 模块 | 你学会了什么 | |
|---|---|---|
| 读世界 | 电位器、光敏、热敏、麦克风 | 模拟输入、ADC、标定 |
| 按钮、红外 | 数字输入、抖动、上拉 | |
| 超声波、DHT11 | 按协议跟模块"对话" | |
| 做动作 | LED、蜂鸣器 | 数字输出——只有开和关 |
| 舵机 | 模拟输出——用 PWM 说出"37 度" | |
| 说出来 | OLED | 把数字变成人能看懂的信息 |
你发现没有——从第 10 课到现在,你其实只学了四件事:读一个值、判断一下、做一个动作、把它显示出来。
零件一直在换,骨架一次都没变过。
这就是「模块熟悉」这个单元的终点。 你现在手上有的不是十个模块的用法,而是一套"拿到新模块该怎么上手"的方法:看丝印、接三根线、先测再猜、跑个最小程序看现象。
说句实在的:这个单元是整套课里最"碎"的一段——十个模块,个个都要接一遍线、调一遍代码,重复得让人有点烦。
但你是走完了的那一个。 多数人是在第三个模块就开始"回头看视频跟着抄"的;而你现在拿到一个没见过的小板子,大概知道从哪儿下手了。
这个本事,比记住十个库的用法值钱。
下一课:让板子上网
下一节是「联网与通信」单元的第一课:第 20 课 WiFi 联网。
前面这 19 节课,你的板子一直活在自己的小世界里——它只知道接在它身上的那几根线。下一课开始,它能连上路由器,能去外面的世界取数据。
不过我要提前给你打个预防针:
联网出问题的时候,你几乎看不见任何东西。
接错一根线,你能看见灯不亮;连不上网,你只能看见"没反应"。所以第 20 课我会专门讲**"连不上网的时候按什么顺序查"**——那套顺序比代码本身值钱。
从"能看见"的世界,跨到"看不见"的世界。这是这块板子真正区别于普通开发板的地方。