手里攒了一堆7针SPI的0.96寸OLED,结果新画的板子上只留了I2C的两根线,这种尴尬场面估计不少人都遇到过。SPI的屏便宜、刷新快,但引脚多;I2C的屏接线省事,可价格往往还贵一点。其实市面上大量7针SPI OLED用的就是同一颗驱动芯片,SPI和I2C两种模式它都支持,只是出厂时通过几个电阻或者BS引脚把模式焊死了。换句话说,只要搞清楚这颗芯片的模式选择逻辑,把该改的跳线改掉,一块SPI屏完全可以当I2C屏用。这篇就围绕"将7针的SPI OLED做I2C使用"这件事,把原理、硬件改法、软件适配和实测踩坑一次讲透,适合手里有SPI屏、又想省引脚或者临时救急的朋友参考。
1. 先搞清楚7针SPI OLED到底"7"在哪
1.1 7个针脚的功能拆解
常见的7针0.96寸OLED模块,针脚排列一般是这样的:GND、VCC、D0、D1、RES、DC、CS。很多人第一次看到会疑惑,SPI不是四根线吗,怎么这里冒出来这么多。原因在于这套接口是"SPI数据线 + 若干控制线"的组合,并不是纯粹的SPI。
- GND / VCC:供电,一般是3.3V,部分模块标称支持3.3V到5V,但实际屏体是3.3V逻辑,5V供电要看板上有没有LDO。
- D0:SPI的时钟线,对应SCLK。
- D1:SPI的数据线,对应MOSI。注意SPI屏基本是单向写,所以没有MISO。
- RES:复位脚,低电平复位。
- DC:数据/命令选择脚,这是SPI模式特有的,高电平表示后面传的是显示数据,低电平表示传的是命令。
- CS:片选,低电平有效。
关键点在于DC和CS这两个脚。I2C协议里根本没有"数据/命令"这种区分,它是靠每个字节后面的控制位来区分的;也没有独立的片选,靠从机地址寻址。所以一块屏要能在SPI和I2C之间切换,芯片内部必须同时具备这两套逻辑,而7针模块恰好把切换需要的引脚都引出来了。
1.2 驱动芯片才是决定能不能改的关键
7针SPI OLED绝大多数用的是SSD1306或者SH1106这两颗驱动IC,兼容的还有SSD1315等。这几颗芯片有个共同特点:它们本身就同时支持SPI和I2C两种接口,具体用哪种,由芯片上的BS0、BS1、BS2三个模式选择引脚(有的封装叫其他名字,本质一样)的电平组合决定。
以SSD1306为例,模式选择大致是这样的逻辑:
| BS2 | BS1 | BS0 | 接口模式 |
|---|---|---|---|
| 0 | 0 | 0 | 8位并口 |
| 0 | 0 | 1 | 4位并口 |
| 0 | 1 | 0 | I2C |
| 1 | 0 | 0 | SPI |
| 1 | 1 | 0 | I2C(部分批次) |
不同厂家、不同封装的组合表会有细微差别,但核心结论是一致的:只要把BS引脚拉到I2C对应的电平组合,芯片就进入I2C模式。这就是"SPI屏改I2C"在硬件层面的全部秘密。
问题在于,模块出厂时这些BS引脚已经在PCB上被电阻或直接走线固定死了,你从外面看不到。所以改造的本质,是找到板上那几个决定模式的电阻,把它们改成I2C需要的接法。
1.3 为什么厂家不直接做成可切换的
有人会问,既然芯片支持,为什么厂家不干脆留个跳线让用户自己选。原因很现实:成本。多一组跳线、多几个焊盘、多一道工序,量产时都是钱。而且SPI和I2C的屏在市场上是分开卖的,做成固定模式反而方便用户直接选型,不用折腾。所以改造这件事,本质上是用户在"逆向"厂家的固定设计,属于典型的DIY操作。
理解了这一层,后面所有的操作就都有了依据:我们不是在"骗"芯片,而是在把它本来就支持、只是被焊死的功能重新打开。
2. 改造前必须确认的三件事
动手之前别急着拿烙铁,先把下面三件事确认清楚,否则很可能白忙一场,甚至把屏搞坏。
2.1 确认你的屏真的是SSD1306/SH1106系
不是所有7针OLED都能改。判断方法有几个:
- 看模块背面丝印:很多模块背面会印驱动型号,比如"SSD1306"、"0.96 OLED"之类。
- 看排针旁边的元件:如果能看到几个标着"0R"的贴片电阻,且位置在芯片附近,那大概率就是模式选择电阻,改造希望很大。
- 看卖家资料:商品页或资料包里通常会写驱动IC型号。
如果背面完全没有任何标识,也没有可辨认的电阻,那就要谨慎了。有些模块用的是定制封装或者把BS引脚直接内部绑定,外面根本改不了。
提示:SH1106和SSD1306在I2C模式下地址和命令基本兼容,但显存组织方式略有差异(SH1106是132列,SSD1306是128列),改完之后如果显示有偏移,多半是这个原因,后面软件部分会讲怎么处理。
2.2 确认模块上有没有I2C需要的上拉电阻
I2C是开漏总线,SDA和SCL都必须有上拉电阻才能正常工作。SPI模块出厂时是按SPI设计的,大概率没有给SDA/SCL配上拉电阻,因为SPI是推挽输出,不需要。
所以改造时你要额外准备两个上拉电阻,典型值是4.7kΩ到10kΩ,接到3.3V。如果主控板上的I2C总线上已经有上拉,那模块这边可以不重复加,但一定要确认总线上至少有一处上拉存在。这一点后面硬件章节会详细说。
2.3 确认主控的I2C地址规划
SSD1306的I2C地址由芯片的SA0引脚决定,通常是0x3C或0x3D。改造后你的屏会占用其中一个地址。如果总线上已经挂了别的I2C设备,要确认地址不冲突。这个在写代码前用I2C扫描程序一跑就知道,属于软件调试阶段的事,但心里要提前有数。
把这三件事确认完,就可以进入真正的改造环节了。
3. 硬件改造:从找到BS电阻到焊好上拉
这一节是整篇的核心,也是最容易翻车的地方。我会把每一步的操作意图讲清楚,而不是只给结论。
3.1 定位模式选择电阻的实操方法
拿到模块,先翻到背面。典型的7针SPI OLED背面会有这么几个东西:驱动芯片(一颗方形黑胶或COG封装)、若干贴片电阻电容、排针焊盘。
模式选择电阻的特征是:它们通常成组出现,阻值为0Ω或者很小的值,一端接芯片的BS引脚,另一端接VCC或GND。你要做的是找出哪几个电阻决定了BS0/BS1/BS2的电平。
实操上有个笨但有效的办法:用万用表蜂鸣档,从芯片的BS引脚(需要查芯片datasheet确定引脚位置)出发,看它连到哪个电阻,那个电阻另一端接的是VCC还是GND。记录下来,对照前面的模式表,就知道当前是什么模式、要改成I2C需要动哪个。
如果查不到芯片引脚定义,还有个经验法:SPI模式下,通常有一个BS引脚被拉高、其余拉低。你在板上找那几个0Ω电阻,看哪个是接到VCC的,把它改成接到GND(或者反过来),多试一两次往往就能命中。当然,前提是你得能安全地改焊。
3.2 改电阻的具体操作与风险控制
改电阻有两种做法:
- 拆掉原电阻,用飞线改接:把决定模式的0Ω电阻吹掉,然后用细漆包线把BS引脚飞到需要的电平(VCC或GND)。这种做法最干净,但需要一定的焊接功底。
- 保留电阻,叠加改接:如果原电阻是接到GND的,而你需要它接VCC,可以直接在BS引脚和VCC之间再焊一个0Ω或小电阻,同时把原来的GND连接断开。但"断开"这一步往往比直接拆还难,所以实际中更推荐第一种。
操作时注意几点:
- 烙铁温度控制在300到330度,风枪温度别超过350度,OLED的COG封装和排线很怕高温,吹久了直接报废。
- 改之前先给板子拍张高清照,万一焊乱了还能对照恢复。
- 飞线用0.1mm左右的漆包线,太粗的线在这么小的焊盘上根本站不住。
注意:如果你对自己的焊接没把握,宁可先在一块废板上练手,也别直接拿唯一的屏开刀。我见过太多人第一刀就把焊盘带下来的。
3.3 上拉电阻怎么加、加在哪
改完模式电阻,接下来解决上拉。I2C的SDA和SCL都需要上拉,典型接法是各接一个4.7kΩ到VCC。
加的位置有两个选择:
- 加在模块上:在模块的SDA、SCL焊盘和VCC之间各焊一个4.7kΩ电阻。优点是模块独立,插到哪都能用。
- 加在主控板上:如果主控板的I2C接口已经带了上拉,模块这边就不用重复加。
判断标准很简单:整条I2C总线上,SDA和SCL各自至少有一个上拉电阻。多了不会坏(只是功耗略增、上升沿更快),少了通信直接失败。
这里有个容易忽略的点:改造后模块的D0变成了SCL,D1变成了SDA,但RES、DC、CS这三个脚在I2C模式下怎么处理?答案是:RES仍然要接(复位用),DC和CS在I2C模式下通常无效,可以悬空,也可以接地,具体看芯片。稳妥起见,把DC和CS接地或者悬空都行,实测大多数模块悬空即可正常工作。
3.4 改造后的接线对照
改完之后,接线从原来的7根变成4根(不含电源的话是2根信号线),对照如下:
| 原SPI针脚 | 改造后I2C功能 | 接主控 |
|---|---|---|
| GND | GND | GND |
| VCC | VCC | 3.3V |
| D0 | SCL | I2C SCL |
| D1 | SDA | I2C SDA |
| RES | RES | 复位脚(可接主控IO或RC复位) |
| DC | 无效 | 悬空或接地 |
| CS | 无效 | 悬空或接地 |
接线时SCL和SDA千万别接反,接反了扫描不到设备,这是新手最常见的错误。
4. 软件适配:从SPI驱动切到I2C驱动
硬件改完只是成功了一半,软件这边如果还按SPI的初始化去写,屏照样不亮。这一节讲软件怎么改。
4.1 初始化序列的差异
SPI和I2C驱动同一颗SSD1306,初始化命令序列其实是一样的,因为命令本身是芯片级的,跟接口无关。区别在于"怎么把命令和数据送进去"。
SPI模式下,送一个字节的流程是:拉低CS,拉低DC(表示命令),发一个字节,拉高CS。送数据则拉高DC。
I2C模式下,流程变成:发起始条件,发从机地址+写位,发一个控制字节(0x00表示后面是命令,0x40表示后面是数据),再发实际内容,发停止条件。
所以软件改造的核心,是把底层的"写字节"函数从SPI实现换成I2C实现,上层的初始化序列和绘图逻辑基本不用动。这也是为什么很多人改完硬件后,只要把驱动库的底层换掉就能跑。
4.2 控制字节:I2C模式的关键
I2C模式下,每次传输前要先发一个控制字节,这个字节的bit6(Co)和bit7(D/C)决定后续字节的性质:
- 0x00:后面跟的是命令。
- 0x40:后面跟的是显示数据。
很多从SPI转过来的驱动库,如果没处理这个控制字节,屏就会花屏或者完全不亮。这是软件改造里最容易踩的坑。
一个典型的I2C写命令函数长这样:
void OLED_WriteCmd(uint8_t cmd) { I2C_Start(); I2C_SendByte(0x3C << 1); // 从机地址+写 I2C_SendByte(0x00); // 控制字节:命令 I2C_SendByte(cmd); I2C_Stop(); }写数据则是把0x00换成0x40。注意地址要左移一位,因为标准I2C的地址字节最低位是读写位。
4.3 用现成库还是自己写
如果你用的是Arduino生态,直接上U8g2或者Adafruit_SSD1306,把构造函数的接口类型改成I2C、填对地址就行,底层它自己处理。如果是STM32这类裸机环境,HAL库有现成的I2C收发函数,把上面那个写命令/写数据的封装写好,剩下的初始化序列可以直接从SPI版本的驱动里搬。
这里给个判断标准:
- 追求快速出效果:用现成库,改两行配置。
- 想彻底搞懂原理或者资源受限:自己写底层,代码量其实不大,SSD1306的初始化序列网上到处都是。
4.4 地址扫描:确认屏真的在线
软件写好后,第一件事不是急着显示内容,而是先跑一个I2C扫描,确认能扫到0x3C或0x3D。扫不到就说明硬件还有问题,别往下走。
扫描代码逻辑很简单:遍历0x00到0x7F,对每个地址发起始条件、发地址、看有没有ACK。有ACK的就是在线设备。这一步能帮你快速区分"是硬件没改好"还是"是软件写错了"。
5. 实测中那些文档不会告诉你的坑
前面讲的都是"应该怎么做",这一节讲"实际做的时候会出什么幺蛾子"。这些是我自己踩过、也看别人踩过的坑,价值比前面的步骤更高。
5.1 改完不亮,先别怀疑芯片
改完第一次上电不亮,90%的情况是下面几个原因,按顺序排查:
- SDA/SCL接反:最常见,没有之一。对调一下再试。
- 上拉电阻没加或没接对:用万用表量SDA、SCL对VCC的阻值,应该是几kΩ,如果是无穷大说明没上拉。
- 模式电阻没改对:芯片还在SPI模式,自然不响应I2C。回去核对BS引脚电平。
- 复位没处理好:RES脚一直拉低,芯片处于复位状态。确认RES有正常的复位时序。
按这个顺序排查,基本能定位到问题。
5.2 能扫到地址但显示花屏
扫到地址说明I2C通信通了,花屏通常是控制字节没发对。检查写命令时是不是发了0x00,写数据时是不是发了0x40。如果控制字节错了,芯片会把命令当数据、数据当命令,显示自然乱套。
还有一种可能是显存列地址范围设错。SSD1306是128列,SH1106是132列,如果你用的是SH1106却按SSD1306的128列去写,右边会缺一块或者整体偏移。解决办法是在初始化里把列地址范围改成0到131。
5.3 通信时好时坏,偶尔丢数据
这种间歇性故障最烦人,常见原因有两个:
- 上拉电阻太大:比如用了100kΩ,上升沿太慢,高速通信时数据采样出错。换成4.7kΩ试试。
- 走线太长或没做屏蔽:I2C本来就不适合长距离,线超过20cm就容易出问题。缩短线长或者降低通信速率。
实测下来,4.7kΩ上拉配100kHz到400kHz的速率,在十几厘米的排线上非常稳。
5.4 改完之后SPI还能不能用
理论上,如果你只是把BS引脚从SPI电平改到I2C电平,那SPI模式就失效了,除非你再改回去。所以这是一次性选择,改之前想清楚。如果确实需要两种模式切换,可以在BS引脚上接一个跳线帽或者拨码开关,手动切换,但要注意切换后软件也要跟着换驱动。
5.5 关于供电的一个提醒
有些7针模块标称5V供电,但屏体是3.3V逻辑。如果你用5V给VCC,同时主控是3.3V的I2C,那SDA/SCL上的电平可能不匹配,长期用会损伤芯片。稳妥做法是VCC和主控都用3.3V,或者确认模块上有电平转换电路。这一点在改造时尤其要注意,因为SPI模式下很多人图省事直接接5V,改I2C后问题就暴露出来了。
6. 这套改造适合谁、不适合谁
把话说明白:这个改造不是万能的,它有明确的适用边界。
适合的场景:
- 手里有闲置的SPI OLED,新项目只留了I2C接口,想废物利用。
- 主控IO紧张,SPI要占4根线,I2C只要2根,省下来的IO能干别的。
- 学习目的,想搞懂SPI和I2C在驱动同一颗芯片时的底层差异。
不适合的场景:
- 对刷新率要求高的场合。I2C速率通常低于SPI,全屏刷新会明显变慢,动画类应用会卡。
- 批量生产。手工改电阻的一致性没法保证,量产还是直接买I2C版本的屏。
- 焊接功底不足又只有一块屏的情况。改坏了就没得用了。
从成本角度算一笔账:一块SPI OLED可能比I2C版本便宜几块钱,但改造要花时间、要买电阻、要承担改坏的风险。如果是单件DIY,省下的钱其实抵不上折腾的时间;但如果是手头正好有屏、又急着用,那这个改造就是救急的好办法。
我个人在实际操作中的体会是,这个改造最大的价值不在于省钱,而在于让你真正理解了"接口"和"驱动芯片"是两层东西。同一颗芯片,换个接口照样工作,这种认知在以后遇到其他模块时同样适用。比如很多传感器也是SPI/I2C双接口的,原理完全一样。改完这块屏之后,再看那些双接口模块,心里就有底了。
最后分享一个小技巧:改之前先用I2C扫描程序在原始SPI屏上跑一遍,如果居然能扫到地址,说明这块屏的BS引脚可能本来就是I2C配置,只是模块按SPI卖的,那你连焊都不用动,直接按I2C接线就能用。这种情况虽然少见,但确实存在,先试一下不亏。