1. I2C协议基础:从一根线到两根线的故事
大家好,我是你们的嵌入式Linux驱动讲师。今天咱们聊聊I2C协议的基础。说实话,我最早接触I2C是在做一款传感器驱动的时候,那时候刚入行,被时序图搞得晕头转向。后来踩了不少坑,才慢慢摸透了它的脾气。
I2C,全称Inter-Integrated Circuit,是飞利浦公司在1982年搞出来的。你想想看,那时候的芯片之间通信,要么并口一大堆线,要么串口速率慢。I2C就聪明了——只用两根线,就能挂一堆设备。这个设计思路,到现在看都不过时。
核心要点:I2C是一种同步、半双工、多主从的串行通信总线。两根线:SDA(数据线)和SCL(时钟线)。
1.1 物理层特性:SDA和SCL到底怎么工作的?
SDA是数据线,SCL是时钟线。这两根线都是开漏输出,需要外部上拉电阻。什么叫开漏?说白了,就是芯片只能把线拉低,不能主动拉高。拉高的工作,交给上拉电阻来做。
我个人习惯把SDA想象成一条“公共汽车道”,SCL就是“红绿灯”。红绿灯(时钟)控制什么时候可以上下车(传输数据)。所有设备都挂在同一条道上,但同一时刻只能有一个设备在说话。
小技巧:我在调试I2C时,第一件事就是量SDA和SCL的静态电平。如果量出来是低电平,那八成是上拉电阻没焊,或者芯片把总线拉死了。这个坑我踩过不下三次。
1.2 电气特性与上拉电阻:选多大才合适?
上拉电阻的取值,其实是个平衡艺术。电阻太小,电流太大,功耗高;电阻太大,上升沿太慢,通信容易出错。
标准模式下,我一般用4.7kΩ。快速模式下,用2.2kΩ。高速模式下,可能要用到1kΩ甚至更小。当然,这跟总线电容也有关系。总线上的设备越多,电容越大,电阻就得选小一点。
| 模式 | 速率 | 推荐上拉电阻 | 总线电容 |
|---|---|---|---|
| 标准模式 | 100 kHz | 4.7kΩ - 10kΩ | < 400 pF |
| 快速模式 | 400 kHz | 2.2kΩ - 4.7kΩ | < 200 pF |
| 高速模式 | 3.4 MHz | 1kΩ - 2.2kΩ | < 100 pF |
注意:我曾经在一个项目里,为了省电把上拉电阻换成了100kΩ。结果总线上升沿慢得像蜗牛,通信时好时坏。查了两天才发现是电阻的问题。嗯,从那以后我再也不敢乱改上拉电阻了。
1.3 I2C与SPI、UART对比:谁更适合你的项目?
很多初学者会问:I2C、SPI、UART,到底选哪个?我的回答是:看场景。
UART,最简单,三根线(TX、RX、GND)就能通信。但它是异步的,双方得约定好波特率。而且只能点对点,不能挂多个设备。我一般用它来做调试串口,或者跟蓝牙模块通信。
SPI,速度快,全双工,四根线(MOSI、MISO、SCLK、CS)。但每加一个设备,就得加一根片选线。设备多了,GPIO不够用。我做过一个项目挂了8个SPI设备,光片选线就占了8个GPIO,心疼得要命。
I2C,就两根线,能挂127个设备。但速度比SPI慢,而且是半双工。适合传感器、EEPROM、RTC这类对速率要求不高的设备。
| 特性 | I2C | SPI | UART |
|---|---|---|---|
| 线数 | 2(SDA + SCL) | 4 + N(N为设备数) | 2(TX + RX) |
| 通信方式 | 半双工 | 全双工 | 全双工 |
| 速率 | 100 kHz - 3.4 MHz | 可达几十MHz | 通常 115200 bps - 几Mbps |
| 多设备支持 | 是(地址寻址) | 是(片选) | 否(点对点) |
| 典型应用 | 传感器、EEPROM | ADC、LCD、Flash | 调试串口、GPS模块 |
说白了,没有最好的协议,只有最合适的。我个人习惯是:需要挂多个低速设备,选I2C;需要高速传输,选SPI;简单点对点通信,选UART。
1.4 I2C协议的核心逻辑:一张图看懂
下面这张图,是我自己画的I2C通信流程。每次给新人培训,我都会先让他们看这张图。理解了它,I2C协议就掌握了一半。
这张图把I2C通信拆成了五个步骤:起始条件、发地址、等应答、传数据、停止条件。其中“传数据”这一步可以循环多次,直到所有数据都传完。
我的经验:调试I2C时,用逻辑分析仪抓一下起始条件和停止条件,基本就能判断通信有没有跑通。如果起始条件都出不来,那肯定是硬件问题,别浪费时间调软件。
1.5 避坑指南:我踩过的那些坑
做I2C驱动这么多年,我总结了几条血泪教训:
- 总线锁死:我曾经遇到过一次,从机在传输过程中突然复位了,结果SDA被拉低不放。主机等不到应答,一直卡死。解决办法是:在驱动里加超时机制,超时后强制产生9个时钟脉冲,让从机释放总线。
- 地址冲突:两个设备用了同一个I2C地址。我查了两天,最后发现是芯片的地址引脚没接对。嗯,硬件原理图一定要仔细对。
- 速率不匹配:从机只支持100kHz,主机却配成了400kHz。通信时好时坏。后来我习惯在驱动里先读从机的设备ID,确认通信正常后再切到高速模式。
重要提醒:I2C的时序要求很严格。SCL的上升沿时间、保持时间、数据建立时间,都有明确要求。如果你的I2C设备工作在恶劣环境(高温、强干扰),建议把速率降到标准模式,同时加上重试机制。
好了,这一章的内容就到这里。I2C协议基础是后面所有章节的基石,尤其是时序图和电气特性,建议大家多看几遍。下一章我们会深入I2C的时序细节,包括如何用逻辑分析仪抓波形、如何分析时序问题。