1. OLED像素电流计算:一个被"能点亮就行"掩盖的真问题
大部分人第一次碰 OLED 模块,注意力都花在 I2C 能不能通、地址对不对、字库取模对不对上。屏幕亮了,字出来了,项目就往下走了。直到某一天电池续航差了 30%、某个批次的模块全黑、或者整机在低温下开不了机,才回过头来问一句:这块屏到底吃多少电流?
OLED 像素电流计算这件事,说穿了就是要回答三个问题:单个像素点亮时流过多少电流、整块屏在当前画面下总共吃多少电流、电源和驱动芯片能不能扛住这个电流。这三个问题一环扣一环,前两个算不清,第三个就没法校核。
我做过不少带 0.96 寸和 1.3 寸 OLED 的便携设备,最惨的一次是第一批 50 台样机全部正常,第二批 200 台里有 37 台开机就是黑屏,剩下能亮的亮度也明显偏暗。查了两天才发现问题出在模组厂换了 IREF 电阻的贴片料号,阻值从 910k 变成了 1M 以上,单像素电流直接掉了一个档位。这件事之后,我把"OLED 像素电流"从一个"用不着算"的常识,变成了硬件评审的必查项。
这篇文章面向的是手上有实际项目的嵌入式/硬件工程师,也适合做 Arduino、STM32 入门但想往"能用"方向走的爱好者。我会从 OLED 发光的物理机制讲起,把单像素电流的来源、整屏电流的估算方法、灰度调光对平均电流的影响、以及怎么用万用表把电流真正量出来,一步步拆开。中间会穿插 SSD1306 这类常见驱动 IC 的寄存器细节和一段可跑的 HAL 库测试代码,也会把批量点不亮、显示不均这类现场问题的排查链路完整走一遍。
2. OLED像素的电流从哪来:先搞懂恒流源在干什么
2.1 电压驱动这条路为什么走不通
LED 和 OLED 都是电流驱动器件,这句话几乎所有教程都会说,但很少有人说清楚"为什么"。核心在于它的伏安特性曲线:在导通阈值附近,电压只要变化几十毫伏,电流就可能翻好几倍。
举个具体感受:一颗 OLED 像素在 3.0V 时可能只走 1μA,微弱到看不见;到 3.3V 可能走 20μA,亮度刚起来;再往上到 3.6V,电流可能已经冲到 300μA,像素在超载状态发光。整个过程电压只变了 0.6V,电流变了 300 倍。这种指数关系意味着,如果你用恒定电压去驱动像素,电源纹波、温漂、批次差异中的任何一点扰动,都会直接放大成亮度的剧烈波动。
更麻烦的是负温度系数。OLED 材料的发光效率随温度升高而下降,但同等电压下电流会上升,两者叠加形成正反馈:温度升高导致电流增大,电流增大导致发热更多,发热又推高温度。这就是所谓的"热失控"苗头。对小屏幕来说不至于烧毁,但显示均匀性会明显变差——温度高的区域更亮,形成"热点"。
结论很直接:OLED 必须用恒流驱动,而且电流源要能容忍面板参数的变化。这就引出了驱动 IC 里的核心结构。
2.2 SEG 供流、COM 接地:无源矩阵的基本结构
以最常见的 SSD1306 为例,它驱动的是 128×64 的无源矩阵 OLED 面板。所谓无源矩阵,就是面板上只有两组正交的电极:128 条 SEG(列)和 64 条 COM(行),每个像素就是 SEG 和 COM 交叉点上的一小块有机发光层,像素本身没有任何晶体管。
点亮某个像素的方式是:让那一列 SEG 输出恒定电流,同时把那一行 COM 拉到低电位,电流从 SEG 流经像素到 COM。其他未选中的 COM 处于高阻或反向偏置状态,电流过不去,像素就不亮。
这里有个关键细节:因为每一时刻只有一行 COM 被选中,所以一帧画面是被切成 64 个时间段轮流扫出来的。SSD1306 的帧率典型在 105Hz 左右,一帧 9.5ms,分给每行大约 148μs。也就是说,每个像素一帧里只有 1/64 的时间在真正发光,其余时间靠人眼视觉暂留补全。
这个"1/64 占空比"是后面算平均电流的基石。瞬时电流和平均电流之间的差距,就是这么来的。
2.3 恒流源的闸门:IREF 引脚上的那颗电阻
驱动 IC 内部不是 128 个独立电流源,那样面积和功耗都受不了。实际做法是电流镜:芯片内部做一个基准电流源,然后按比例镜像到每一路 SEG 输出。基准电流的大小由 IREF 引脚外接的电阻 Rref 决定。
内部逻辑大致是这样:IREF 引脚内部会建立一个参考电压 Vref,外部电阻 Rref 接在 IREF 和地之间,流过 Rref 的电流就是 Iref = Vref / Rref。这个 Iref 被镜像到每一路 SEG,形成段驱动电流 Iseg,两者的比例系数由芯片内部设计固定。
所以整条链路是:
Rref → Iref → 镜像系数 → Iseg → 单像素瞬时电流数据手册里通常会有一张 "IREF Setting" 的对应表或曲线,列出不同 Rref 下的典型 Iseg。这张表必须以你手上那版手册为准,不同厂商、不同版本的 SSD1306 兼容芯片(比如常见的国产替代)给出的数值可能不完全一致。
市面上 0.96 寸模块最常用的 Rref 是 910kΩ,也有用 1MΩ 甚至 560kΩ 的。Rref 越小,Iseg 越大,屏幕越亮,功耗越高。这就是为什么我前面提到的批次事故会致命——模组厂悄悄换了电阻值,软件侧完全无感知,但实际电流已经变了。
提示:如果你在设计自己的板子而不是用现成模块,Rref 建议选 1% 精度的金属膜电阻,不要用碳膜。电流镜对 Rref 的绝对精度敏感,5% 的电阻误差意味着 5% 的亮度差异,多块屏并排时会看出来。
2.4 对比度寄存器:给电流加一个 8 位乘数
硬件上的 Rref 决定的是"电流上限",实际运行时的电流还受一个软件寄存器控制,也就是 SSD1306 的对比度寄存器(命令 0x81,后跟一个字节参数)。
这个 8 位参数的范围是 0x00 到 0xFF,映射关系近似线性:0x00 对应最小电流,0xFF 对应满电流。换成人话,亮度比例约等于 (contrast + 1) / 256。
常见驱动库默认写的是 0xCF,也就是 207。207/256 ≈ 0.81,意味着默认只用了 81% 的电流能力。有些库写 0x7F(127),那就只有一半;写 0xFF 则是打满。
这个寄存器是软件层面唯一能实时调电流的入口,也是做呼吸灯效果、夜间模式、按环境光自动调亮度的抓手。理解它的量化关系,你就能把"亮度"从一个模糊的百分比,变成一个可计算的电流比例。
3. 从单像素到整屏:把电流算成一张账单
3.1 理论公式长什么样
把前面几节串起来,可以先写一个理论上限的估算式:
I_avg ≈ K × N_on × (contrast + 1) / 256 × D + I_q各项含义:
I_avg:折算到面板侧的平均电流K:由 Rref 决定的单像素满电流系数N_on:当前画面中处于点亮状态的像素总数contrast:对比度寄存器值,0 到 255D:扫描占空比,SSD1306 在 64 行模式下约为 1/64I_q:IC 静态电流与电荷泵空载损耗
这个式子在你手上没有手册、需要快速判断量级时很有用,但它有个现实问题:K和D的乘积很难从手册直接读出来,手册给的是 Iseg,而 Iseg 是瞬时值,你要自己乘占空比。
3.2 工程上更实用的做法:实测系数法
我在实际项目里更愿意用实测标定 + 线性外推的方式,原因是它把所有不确定因素(手册版本差异、模组差异、电荷泵效率、面板效率)全部一次性打包进一个系数里,比纯理论计算准得多。
操作思路是:在固定对比度下,分别测"全黑"和"全白"两种画面的 VCC 电流,差值除以像素总数,就得到每个点亮像素折算到电源侧的平均电流系数。
以我手上几块常见的 0.96 寸模块为例,VCC = 3.3V、对比度设为 0xCF 时:
| 画面状态 | 点亮像素数 | 实测 VCC 电流 | 说明 |
|---|---|---|---|
| 全黑(显示关闭,仅电荷泵工作) | 0 | 约 1.5 到 3 mA | 主要是 IC 静态 + 电荷泵空载 |
| 单行汉字(16×16,2 个字) | 约 512 | 约 4 mA | 与全黑差值 1 到 2 mA |
| 半屏文字 | 约 4000 | 约 12 mA | 中间量级 |
| 全屏点亮 | 8192 | 约 20 到 23 mA | 满负荷 |
按全白数据反推,每点亮像素折算到 VCC 侧约为 (22 - 2) mA / 8192 ≈ 2.4μA。这个系数就是你的"账单单价",之后算任何画面都只需要数像素。
屏幕上显示一个 16×16 汉字,笔画实际点亮的像素大概在 90 到 130 个之间,不是 256 个。一副满屏图片如果黑白各半,实际点亮约 4096 个点。这些数字你得根据实际取模数据去数,而不是按面积拍脑袋。
3.3 对比度一改,整张账单跟着变
上一节的系数是在 0xCF 下测的。如果把对比度调到 0xFF,系数大致按 256/208 ≈ 1.23 倍放大,全白电流会到 26mA 左右。调到 0x7F,则缩到约 0.61 倍,全白约 13mA。
这个线性关系在中间区间成立得不错,但在极低值区域(比如 0x00 到 0x0F)会明显偏离,因为芯片在这个区间的最小步进有特殊处理。所以我一般的做法是:在 0x20 到 0xFF 之间用线性模型做估算,低于 0x20 的部分一律靠实测。
下面这张表是我常用的参考,方便开机前做个快速预算:
| 对比度设置 | 相对电流比例 | 全白 8192 点预估电流(含静态) |
|---|---|---|
| 0x7F(127) | 约 0.61 | 约 14 mA |
| 0x9F(159) | 约 0.76 | 约 17 mA |
| 0xCF(207) | 1.00(基准) | 约 22 mA |
| 0xE0(224) | 约 1.07 | 约 24 mA |
| 0xFF(255) | 约 1.22 | 约 27 mA |
注意这里的"含静态"是指折算到 VCC 3.3V 侧的整机电流。如果你把电流探头放在电荷泵输出端(也就是面板实际工作电压,通常在 7V 到 8V 之间),读数会小很多,因为电压高、电流低,功率是守恒的。这一点在对比厂家规格书时特别容易踩坑,规格书标的到底是 VCC 侧还是面板侧,必须看清楚。
3.4 电源预算里的三个隐藏项
把整屏电流算出来之后,很多人就直接拿这个数去挑 LDO 了,这中间漏了三个东西。
第一个是 I2C 总线的动态电流。128 字节一帧的数据量,在 400kHz 下传输需要约 2.9ms,加上首字节和 ACK,实际更长。如果刷新率设到 60Hz,光总线传输就占掉大量时间,MCU 侧和上拉电阻侧的电流不能忽略。上拉电阻越小,总线翻转时的瞬时电流越大,4.7k 上拉在 3.3V 下翻转峰值接近 0.7mA。
第二个是电荷泵的启动冲击。SSD1306 内部电荷泵从 3.3V 升到 7.5V 左右,上电瞬间要给面板电容充电,会出现一个持续时间很短但幅值不小的浪涌。如果你的电源是纽扣电池或者小容量锂电,这个浪涌可能直接把电压拉塌,导致 IC 复位、屏幕不亮。这就是为什么"用万用表看电压正常但屏就是不亮"的情况会出现在电池供电设备上。
第三个是温度。前面说过 OLED 有负温度系数,同一个画面在 60 摄氏度环境下的电流会比 25 摄氏度时高出一截。做工业设备或者车载应用时,电源预算要按最高工作温度来留余量,我一般会按常温值的 1.3 到 1.5 倍去设计。
4. 灰度和扫描:平均电流和峰值电流是两码事
4.1 占空比带来的"功率税"
无源矩阵的逐行扫描,本质上是一种时间上的功率压缩。要让一行的像素在 148μs 内发出足够亮的光,瞬时电流必须远大于平均电流。这就是无源 OLED 的"功率税"——同样的视觉亮度,无源矩阵的峰值电流是有源矩阵(AMOLED)的几十倍。
理解这一点,你才能解释几个现象:为什么 OLED 全白时电流表读数会跳得厉害;为什么大电流点亮的画面下屏幕容易出现横向条纹;为什么给 OLED 做去耦时,1μF 不够,得并上 10μF 甚至 22μF。
峰值电流大,对电源的瞬态响应要求就高。LDO 的负载瞬态响应跟不上,输出电压就会在每行扫描的瞬间往下掉一点,表现为屏幕整体亮度略降或者出现扫描纹。我遇到过一次,用了一颗静态电流极低(几百 nA)的 LDO 做低功耗设计,结果全屏显示时噪点明显,换了颗静态电流 20μA 但瞬态响应好的型号,问题立刻消失。低功耗和瞬态响应,很多时候是矛盾的,做便携设备必须权衡。
4.2 SSD1306 的灰度是怎么"造"出来的
SSD1306 是单色驱动的,每个像素只有亮和灭两种状态,数据按 1bpp 存储,每个字节管 8 个像素。那屏幕上那些看起来深浅不一的灰色是怎么来的?
答案是时间抖动(dithering)。软件层面用有序抖动或者误差扩散算法,把灰度值映射成一片亮灭相间的像素图案,人眼在正常观看距离下会把它平均成灰色。比如 50% 灰度就是用棋盘格图案实现的。
这里的关键点在于:抖动算法不改变点亮像素的总数,但改变它们的空间分布。一张 50% 灰度的图,点亮像素数是 4096,跟一张黑白各半的图完全一样,所以电流也一样。但如果抖动后的图案让某一行的点亮数特别多,那行的瞬时电流就会偏高。
这也是为什么我在做低功耗界面设计时,会尽量避开大面积 50% 灰度的背景。看起来只是"淡一点的底纹",电流上和半屏全亮没区别。
4.3 想真正省电,得从像素数量下手
因为平均电流和点亮像素数成正比,省电的核心思路就是减少点亮像素,而不是单纯调低亮度。
具体做法有这么几个:
- 深色主题优于浅色主题。白色背景意味着接近 100% 的点亮率,黑色背景接近 0%。同样一个界面,深色主题的电流可能只有浅色主题的 15%。
- 用点阵字体代替笔画字体。16×16 的全角汉字平均点亮 100 个像素左右,而 8×16 的 ASCII 字符只有 20 到 30 个。同样信息量下,ASCII 界面的电流小一个数量级。
- 避免满屏充填的进度条和色块。一个 100×8 的实心进度条就是 800 个像素常亮,相当于 8 个汉字一直在那耗电。可以改成描边加动态点。
- 动态降低对比度。在环境光暗的场合,把对比度从 0xCF 降到 0x9F,电流能降 25%,肉眼几乎看不出差别。
注意:调对比度省电是线性的,减少像素数省电也是线性的,两者可以叠加。但如果你的设备是电池供电,优先动像素数,因为它不影响可读性。
5. 把电流真正量出来:一段测试代码加一块万用表
5.1 测量点怎么选
理想情况下,你应该在最靠近 OLED 模组 VCC 引脚的地方串一个电流表。实际操作中,串万用表会引入压降,可能影响结果,所以我更推荐两种方式。
一种是用可调电源自带的电流显示。把限流设到 100mA,电压设到 3.3V,直接读电源上的电流值。这种方法最省事,缺点是分辨率通常在 1mA 一档,测小电流不准。
另一种是串一个小阻值采样电阻。在电源和模组 VCC 之间串一个 0.1Ω 的 1% 电阻,用高精度万用表测它两端的电压差,除以 0.1 就是电流。1mA 电流对应 0.1mV,普通手持表的 200mV 档能分辨,准确度不错。缺点是采样电阻会带来少量压降,0.1Ω 在 20mA 下只有 2mV,可以忽略。
不管用哪种方式,测点必须在模组的 VCC 引脚根部,不能测到你 MCU 板上的电源入口,否则中间走线的压降、其他器件的电流都会被算进来。
5.2 差值法:把静态电流从账单里剔掉
单次读数是没意义的,因为里面混着 IC 静态电流、电荷泵空载电流、上拉电阻电流。真正有用的做法是测两次,做差。
- 先发命令
0xAE(关闭显示),等两秒稳定,记录电流 I_off。 - 再发
0xAF(打开显示),显示全屏点亮的图案,稳定后记录 I_on。 - 差值 I_on - I_off 就是 8192 个像素贡献的电流。
- 除以 8192,得到单像素系数。
这个方法的好处是,所有跟像素无关的固定开销都被自动消掉了。而且因为是差值,万用表的绝对精度影响也被削弱了。
5.3 HAL 库下的测试图案代码
下面这段是基于 STM32 HAL 库、I2C 接口 SSD1306 的最小测试代码,用来配合上面的测量流程。先说清楚控制字节的约定:I2C 传输的第一个字节是控制字节,0x00表示后面跟的是命令,0x40表示后面跟的是显存数据。
/* 7 位地址 0x3C 左移一位得到 0x78 */ #define OLED_ADDR (0x3C << 1) /* 发送单条命令 */ static void oled_cmd(uint8_t cmd) { uint8_t buf[2] = {0x00, cmd}; HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, buf, 2, HAL_MAX_DELAY); } /* 发送带参数的命令 */ static void oled_cmd2(uint8_t cmd, uint8_t arg) { uint8_t buf[3] = {0x00, cmd, arg}; HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, buf, 3, HAL_MAX_DELAY); } /* 设置对比度:0x00 ~ 0xFF */ void oled_set_contrast(uint8_t value) { oled_cmd2(0x81, value); } /* 全屏填充:0xFF 全亮,0x00 全灭 */ void oled_fill(uint8_t pattern) { uint8_t buf[129]; buf[0] = 0x40; for (uint16_t i = 1; i <= 128; i++) { buf[i] = pattern; } /* 8 页,每页 128 字节 */ for (uint8_t page = 0; page < 8; page++) { oled_cmd(0xB0 | page); oled_cmd(0x00); oled_cmd(0x10); HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, buf, 129, HAL_MAX_DELAY); } } /* 显示开关 */ void oled_display_on(void) { oled_cmd(0xAF); } void oled_display_off(void) { oled_cmd(0xAE); }测量流程对应到代码就是:
oled_set_contrast(0xCF); /* 固定对比度,保证可比性 */ oled_fill(0x00); /* 显存清空,但显示还开着 */ oled_display_on(); HAL_Delay(2000); /* 此时屏幕全黑但显示开启,记录一次电流 I_blank */ oled_fill(0xFF); /* 全屏点亮 */ HAL_Delay(2000); /* 记录电流 I_full,差值即为 8192 个像素的贡献 */ oled_display_off(); /* 记录 I_off,用于校核静态电流 */有个细节要注意:oled_fill(0x00)之后屏幕全黑,但 IC 和电荷泵还在跑,这时候的电流才是真正的"零像素基线"。如果你直接oled_display_off()去测基线,测到的是显示关闭状态,电荷泵通常也会停,和显示开启但全黑的电流不一样。
5.4 实测数据和理论值对不上怎么办
如果你按上面流程测出来的单像素系数,和手册推算值差了 3 倍以上,先别怀疑自己的代码,按下面顺序排查:
| 现象 | 可能原因 | 验证方法 |
|---|---|---|
| 测出的系数明显偏小 | 采样点不在模组 VCC 根部,被其他负载分流 | 换个测点重测 |
| 全黑基线异常高(>8mA) | 模组上有额外的电平转换或稳压电路 | 看模组原理图 |
| 不同模块差异大 | Rref 电阻批次不一致 | 万用表量 IREF 对地阻值 |
| 对比度改 0xC0 和 0xF0 电流几乎不变 | 库在初始化后又覆写了对比度 | 抓 I2C 波形看有没有多余的 0x81 |
| 读数跳动不停 | 画面在刷新,或电源瞬态 | 停刷新再测,电源并电容 |
我遇到过最常见的一种情况,是驱动库在oled_init()里设了对比度,然后主循环里又调了一次亮度调节函数,两次叠加。测的时候以为设的是 0x9F,实际芯片里是 0xCF,怎么算都对不上。抓一次 I2C 波形比对着代码猜快得多。
6. 批量点不亮与显示不均:从电流视角走一遍排查链路
6.1 最隐蔽的一条:IREF 通路配置
前面提到的 50 台好、200 台有 37 台黑的事故,根因就在 IREF。
SSD1306 支持内部基准和外部基准两种模式,通过命令0xAD后跟参数选择:0xAD, 0x8E表示使用内部 IREF,0xAD, 0x10表示使用外部 IREF。很多网上流传的初始化序列里根本没有这一条,芯片就保持在上电默认状态。
如果你的模组是外部 IREF 设计(板上焊了 Rref 电阻),而软件没设置,那用的是默认通路,一般能亮。但如果模组厂为了省成本做了改动,或者 Rref 虚焊、漏贴、阻值贴错,屏幕就会表现为极暗甚至全黑,但 I2C 通信完全正常。
这种情况下你去查 I2C 地址、查复位、查电源,全都是对的,就是找不到问题。判据很简单:用示波器或逻辑分析仪确认命令都发出去了、ACK 都正常,但屏幕不亮,就去量 IREF 引脚对地的电阻。
我的做法是在初始化序列里显式加上这一条,把行为确定下来:
/* 显式声明使用内部 IREF,避免依赖上电默认值 */ oled_cmd2(0xAD, 0x8E);如果模组用的是外部 IREF 且 Rref 精度更好,就用0xAD, 0x10。关键是不要留空,留空就意味着你的产品行为依赖芯片的默认状态,这在批量生产里是隐患。
6.2 电源侧:LDO 带不动是什么表现
从电流角度看,还有一类"点不亮"是电源能力不足。典型场景是用了一颗输出能力 50mA 的 LDO,理论上全白 22mA 够用,但实际上:
- 电荷泵启动浪涌可能瞬时抽到 80mA 以上
- 如果同时还有 MCU、无线模块在工作,总电流逼近 LDO 上限
- LDO 进入限流或过温保护,输出电压跌落
表现就是屏幕在特定画面下闪烁、局部变暗,或者 MCU 因为电压不足而复位。解决办法有两个:输出端并一个 22μF 到 47μF 的钽电容或者低 ESR 陶瓷电容,把浪涌吸掉;或者换一颗输出能力翻倍的 LDO。
我在低功耗设备上还踩过一个坑:为了省电选了一颗超低静态电流的 LDO,但它的瞬态响应很差,屏幕扫描时每次峰值电流都会让输出掉几十毫伏,结果就是屏幕上有明显的横向亮暗条纹。换 LDO 之后干净了。低静态电流和快瞬态响应,在选型时基本是二选一。
6.3 显示不均匀:可能是电流分布的问题
如果屏幕能亮,但某些区域明显比别处暗,先别急着怀疑面板质量。有两种情况跟电流直接相关。
一种是电源走线的 IR 压降。模组的 VCC 引脚和 FPC 排线本身有电阻,电流流过时会产生压降。全屏点亮电流大,压降就大,靠近电源入口的区域和远端区域亮度就有差异。这种问题在长排线的模块上更明显。
另一种是每行点亮像素数差异造成的扫描电流不均。前面说过,一帧里每一行被轮流点亮,如果某一行的点亮像素数远多于其他行,那一行扫描时电源负担就重,输出电压跌落,这一行整体会偏暗。用户看到的就是"某一行比别处暗"。
验证方法很简单:显示一个全黑背景加一条横线,把这条线在不同行之间移动,看它亮度是否一致。如果移动到某几行时明显变暗,问题就出在电源瞬态上,加去耦电容或者提高刷新率通常能缓解。
提示:显示不均匀很多时候不是屏的问题,而是你的电源和去耦没做够。在怀疑屏之前,先把手边最大的电容并在模组 VCC 引脚上试一次。
7. 亮度、功耗与寿命之间那笔账
7.1 亮度换寿命,是真的
OLED 是有机材料,发光靠的是载流子复合。电流密度越大,复合越剧烈,材料老化越快。行业的经验规律是:亮度翻倍,寿命大致减半。
对 0.96 寸这种小屏,把对比度从 0xCF 拉到 0xFF,亮度提升约 20%,寿命损失大约 30%。如果你的产品要求长时间连续点亮,比如工业仪表面板、充电桩显示,这个取舍就要认真对待。
我自己的做法是:出厂默认对比度设 0x9F 到 0xB0 之间,把 0xFF 留给用户手动调节或者在强光环境下启用。这样既保证日常可读性,又给寿命留了余量。反正大多数室内场景下,0x9F 的亮度已经足够。
7.2 老化和残影:从像素电流角度看
长时间显示同一画面会导致残影,也就是常说的"烧屏"。根本原因是长期点亮的像素老化更快,发光效率下降,而不常点亮的像素保持原有效率,两者亮度差异被人眼看出来了。
从电流角度看,这意味着:当你发现屏幕有残影时,那部分像素的发光效率已经下降了,同样的电流下它们会更暗。你没法通过提高对比度把残影"补回来",因为那是要提升整体电流,正常像素会变得更亮,差异反而放大。
预防的办法都是围绕"让每个像素点亮时间尽量均衡":
- 定期做像素刷新,把整屏反相显示几十秒
- 界面设计上避免固定的边框、分隔线长时间不动
- 显示内容整体做几个像素的慢速平移,行业内叫像素偏移
这些手段在电视和手机上很成熟,嵌入式的 OLED 屏大多不做,但如果你做的是长期运行的设备,值得加上。
7.3 我的默认配置
做了几个项目之后,我形成了一个固定的默认配置,直接抄可以省很多调试时间:
- 对比度默认 0x9F,提供设置接口供上层调整
- 初始化里显式设置
0xAD, 0x8E(或按模组选外部 IREF),不留默认 - 模组 VCC 引脚就近放 10μF 钽电容加 100nF 陶瓷电容
- I2C 上拉 4.7k,走线短于 10cm 时不加缓冲
- 刷新率控制在 30Hz 以内,界面刷新做局部更新,不做全屏重绘
- 深色主题为默认,浅色主题作为可选项
这套配置在 3.3V 供电、全屏文字刷新的典型场景下,整机电流稳定在 8 到 12mA,对大多数电池供电设备都是可接受的。如果还要更省,就上局部刷新加低对比度,能压到 5mA 上下。
最后说一个我踩过两次的坑:别在测电流的时候让屏幕显示动态画面。有一次我测了半天,每次读数都不一样,从 6mA 跳到 15mA,查了两小时才发现是界面里有个进度条动画在跑。测电流之前先冻结画面,或者干脆关掉刷新,让静态数据说话,这是最基本的纪律。
另外,如果你手上只有普通的万用表,测全黑和全白的差值同样有效,只要两次测量的条件完全一致就行。真正的难点不在仪器精度,而在于你有没有把"哪些变量必须固定住"想清楚。对比度、画面内容、刷新状态、供电电压,这四个变量任何一个变了,测出来的数就没有可比性。