2. 硬件接口基础:SPI与I2C协议对比、4线SPI与3线SPI区别、I2C地址配置
做OLED驱动,第一关就是选通信接口。说白了,你得决定用SPI还是I2C把数据灌进驱动芯片里。我见过不少新手上来就抄代码,结果屏幕死活不亮,最后发现是接口模式没配对。这一节咱们就把SPI和I2C的底裤扒干净。
2.1 SPI vs I2C:核心差异
先看一张对比表,心里有个谱。
| 对比项 | SPI(4线) | I2C |
|---|---|---|
| 信号线数量 | 4根(SCLK, MOSI, MISO, CS) | 2根(SCL, SDA) |
| 通信模式 | 全双工 | 半双工 |
| 速率 | 典型10-80 MHz | 标准100 kHz / 快速400 kHz / 高速3.4 MHz |
| 从机选择 | 独立CS引脚,一对一或菊花链 | 7位/10位地址,总线仲裁 |
| 硬件复杂度 | 引脚多,但协议简单 | 引脚少,但协议复杂(ACK/NACK) |
| OLED适用场景 | 高刷新率、大分辨率(128×64以上) | 低引脚数、小尺寸、低功耗 |
我个人习惯:如果MCU引脚够用,优先选SPI。为什么?因为刷屏快。你想想看,128×64的OLED,一帧数据是1024字节。用400 kHz的I2C传,光数据就得20多毫秒,加上命令和地址开销,30帧都跑不满。而SPI轻松上10 MHz,一帧1毫秒搞定。
但I2C也有它的主场。比如你手上只有一颗8引脚的MCU,或者需要挂多个传感器共享总线,那I2C就是天选之子。
关键结论:SPI快但费引脚,I2C省引脚但慢。选哪个,取决于你的刷新率要求和引脚预算。
2.2 4线SPI与3线SPI的区别
很多OLED驱动芯片(比如SSD1306、SH1106)都支持两种SPI模式:4线SPI和3线SPI。这里有个坑,我当年就踩过。
4线SPI:标准的四根线——SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。全双工,一发一收同时进行。
3线SPI:只有三根线——SCLK、MOSI(兼做MISO)、CS。半双工,数据线分时复用。发送时当MOSI用,接收时当MISO用。
等等,OLED驱动芯片需要接收数据吗?
嗯,这里要注意。大多数OLED驱动芯片是只写设备——你只管往它肚子里灌数据,它不会给你回传像素值。所以MISO这根线其实是浪费的。3线SPI就是把这个冗余砍掉了。
| 特性 | 4线SPI | 3线SPI |
|---|---|---|
| 数据线 | MOSI + MISO 独立 | SDATA 双向复用 |
| 通信方向 | 全双工 | 半双工 |
| 引脚数 | 4 | 3 |
| OLED适用性 | 兼容所有SPI主机 | 节省1个引脚,适合引脚紧张场景 |
| 驱动配置 | 默认模式 | 需在初始化命令中切换 |
我曾经在一个项目中,MCU只剩3个空闲GPIO,硬着头皮上了3线SPI。结果发现,有些OLED模块的3线模式需要额外发一个控制字节来区分命令和数据,时序比4线复杂一点。所以我的建议是:除非引脚真的不够,否则老老实实用4线SPI。
避坑指南:我曾经买过一批号称“4线SPI”的OLED模块,结果板子上MISO引脚根本没焊。后来一查手册,芯片默认就是3线模式。所以买模块前,一定先看数据手册的接口配置表。
2.3 I2C地址配置
I2C的地址配置,是另一个容易翻车的地方。OLED驱动芯片的I2C地址通常是7位的,但不同芯片、不同模块的地址可能不一样。
以SSD1306为例,它的I2C地址由SA0引脚的电平决定:
- SA0接GND:地址 0x3C(7位地址)
- SA0接VCC:地址 0x3D(7位地址)
但注意,很多库函数里写的是8位地址(左移一位后的值)。比如0x3C左移一位变成0x78。你写代码时一定要搞清楚库用的是7位还是8位地址。我见过有人把0x3C直接当8位地址传进去,结果I2C总线一直NACK,屏幕死活不亮。
警告:I2C地址的7位/8位混淆是OLED驱动中最常见的bug之一。建议在代码开头用宏定义明确标注:#define OLED_I2C_ADDR_7BIT 0x3C,并在注释里写明是7位还是8位。
另外,有些OLED模块(比如0.96寸的常见款)会把SA0引脚通过电阻固定到GND,地址就是0x3C。但也有模块把SA0引出到焊盘,让你自己跳线。买模块时多看一眼原理图,能省去后面一小时的调试时间。
2.4 知识结构图:接口选择与配置流程
下面这张图把整个决策过程串起来了。你可以把它当作一个快速参考。
2.5 实战要点总结
- SPI选型:引脚够用就上4线SPI,省心。3线SPI只在你数着引脚过日子的时候用。
- I2C地址:先查模块原理图或数据手册,确认SA0电平。代码里明确标注地址是7位还是8位。
- 速率匹配:SPI时钟不要超过芯片手册标称最大值(常见10 MHz)。I2C用400 kHz通常没问题,但长线缆时降到100 kHz更稳。
- 上拉电阻:I2C的SCL和SDA必须外接上拉电阻(4.7 kΩ典型值)。SPI的CS引脚建议接上拉,防止浮空误触发。
我的习惯:每次拿到新OLED模块,第一件事不是写代码,而是用逻辑分析仪抓一下初始化时序。看一眼波形,接口模式、地址、速率全清楚了。这比对着手册猜快得多。