I2C 协议
I2C(Inter-Integrated Circuit,原名 Inter-IC)是一种短距离串行通信协议,由 Philips 公司开发。由于其简单的两线制设计(时钟线 SCL 和数据线 SDA),I2C 协议被广泛应用于连接微控制器与各种外设,如传感器、EEPROM、RTC、AD/DA 转换器等。
I2C 协议原理
两线制接口
I2C 仅使用两根信号线:
| 信号线 | 全称 | 说明 |
|---|---|---|
| SCL | Serial Clock | 时钟线,由主设备产生 |
| SDA | Serial Data | 数据线,双向传输 |
开漏输出与上拉电阻
I2C 总线要求 SDA 和 SCL 必须使用开漏(Open-Drain)输出模式,并通过上拉电阻连接到正电源:
VCC
│
├─ Rp (上拉电阻 4.7k~10kΩ)
│
┌────┴────┐
│ SDA │ ← 开漏输出
└────┬────┘
│
┌────┴────┐
│ 设备1 │ ← I2C 器件
│ 设备2 │
│ ... │
└─────────┘
为什么使用开漏输出? -允许多个设备共享同一总线而不产生电平冲突
- 实现"线与"功能:任一设备拉低,总线即为低电平
- 支持仲裁和时钟同步
推挽输出 vs 开漏输出
| 模式 | 能主动输出 | 能主动输出 | 适用场景 |
|---|---|---|---|
| 推挽输出 | 高电平 | 低电平 | 单设备驱动 |
| 开漏输出 | 高电 平(需上拉) | 低电平 | 多设备共享总线 |
I2C 时序
空闲状态
当总线没有进行任何传输时,SCL 和 SDA 都处于高电平状态(被各自的上拉电阻拉高)。
起始条件(Start Condition)
起始条件由主设备发起:SDA 线从高电平切换到低电平,然后 SCL 线从高电平切换到低电平。
空闲 起始条件
SDA ──────────┐ ┌─────────────
└────┘ (SDA 由高变低)
SCL ───────── ──────┐
└─────────────
(SCL 保持高后变低)
停止条件(Stop Condition)
停止条件由主设备发起:SCL 线从低电平切换到高电平,然后 SDA 线从低电平切换到高电平。
停止条件
SDA ────────────────┐
└──────── ────
SCL ───────────────────────┐
└────
数据有效性
I2C 的数据采样发生在 SCL 的高电平期间。在 SCL 为高电平时,SDA 线上的电平必须保持稳定:
┌───┐
SCL ─────┘ └──────
↑ 采样点
┌───┐
SDA ─────┘ X └──────
↑ 保持稳定
SDA 在 SCL 高电平期间的变化表示:
- 从高到低 = 起始条件
- 从低到高 = 停止条件
数据传输格式
每个字节(8位)后面跟随一个应答位(ACK/NACK):
8 bits数据 ACK/NACK
┌──────────────────┐ ┌────┐
│ D7 D6 D5 D4 D3 D2 D1 D0 │ │ ACK │
└──────────────────┘ └────┘
↑
第9个时钟周期
MSB 在前(Most Significant Bit 先传输)
应答机制(ACK/NACK)
应答位(ACK):
- 发送方在第9个时钟周期释放 SDA 线(设为高阻态)
- 接收方在 SCL 的高电平期间将 SDA 拉低
- 表示数据已被正确接收
非应答位(NACK):
- 接收方在第9个时钟周期保持 SDA 为高电平
- 可能的原因:
- 接收方不希望接收更多数据
- 发送方发送的地址没有设备 响应
- 接收方在接收过程中发生错误
完整的数据传输过程
1. 主机发送 START 条件
2. 主机发送 7 位地址 + R/W 位
3. 主机释放 SDA,等待从机 ACK
4. (如果是写操作) 主机发送 8 位数据,等待 ACK
5. (如果是读操作) 从机发送 8 位数据,主机发送 ACK
6. 重复步骤 4 或 5,可以传输多个字节
7. 主机发送 STOP 条件
I2C 地址
7位地址格式
I2C 设备使用 7 位地址(不包括 R/W 位):
6 5 4 3 2 1 0
┌──┬──┬──┬──┬──┬──┬──┐
│ 设备地址 │R/W│
└──┴──┴──┴──┴──┴──┴──┘
常见设备的 I2C 地址
| 设备 | 典型地址(7位) | 说明 |
|---|---|---|
| OLED SSD1306 | 0x3C 或 0x3D | 128x64 OLED 显示屏 |
| MPU6050 | 0x68 或 0x69 | 六轴加速度计/陀螺仪 |
| BMP180 | 0x77 | 气压传感器 |
| AT24C02 | 0x50~0x57 | 256 字节 EEPROM |
| PCF8574 | 0x20~0x27 | I/O 扩展芯片 |
| ADS1115 | 0x48~0x4B | 16 位 ADC |
10位地址格式
I2C 还支持 10 位地址,使用两个字节传输:
First byte: 1111 0XX + R/W
Second byte: XXXXXXXX
STM32 I2C 寄存器详解
I2C_CR1 - 控制寄存器 1
| 位 | 名称 | 说明 |
|---|---|---|
| 15 | SWRST | 软件复位 |
| 14 | SMBUS | SMBUS 模式(0=I2C 模式) |
| 10 | SMBTYPE | SMBus 类型 |
| 9 | ENARP | ARP 使能 |
| 8 | PEC | PEC 使能 |
| 7 | POS | 应答/PEC 位置 |
| 6 | ACK | 应答使能 |
| 5 | STOP | 停止条件生成 |
| 4 | START | 起始条件生成 |
| 3 | NOSTRETCH | 时钟拉伸禁止 |
| 2 | ENGC | 广播呼叫使能 |
| 1 | ENPEC | PEC 校验使能 |
| 0 | PE | I2C 使能 |
I2C_CR2 - 控制寄存器 2
| 位 | 名称 |
|---|