一、I2C
I2C(Inter-Integrated Circuit,集成电路总线) :由飞利浦(现NXP)提出的两线制同步串行通信总线,用于主机与从机(通常是MCU与外围芯片)之间的短距离板级通信。
1. 两根线
| 信号线 | 全称 | 作用 |
|---|---|---|
| SCL | Serial Clock,时钟线 | 主机发出,同步整个通信节拍 |
| SDA | Serial Data,数据线 | 双向传输数据(半双工) |
两线均为开漏输出 + 上拉电阻结构,空闲时总线为高电平(线与特性)。
2. 主要特性
| 特性 | 说明 |
|---|---|
| 同步方式 | 同步通信(有时钟线SCL) |
| 数据方向 | 半双工(SDA一根数据线分时双向) |
| 位传输顺序 | 高位先行(MSB first) |
| 寻址方式 | 起始信号后第一个字节 = 设备地址(高7位)+ 数据流向位(低1位) ,可挂 127个从机(2⁷=128,保留全0地址,实际可用127个) |
| 通信速率 | 100kHz(标准)、400kHz(快速)、1.xM、3.xM(高速) |
| 拓扑 | 一主多从 / 多主多从,每个从机有唯一7位地址 |
3. 地址与读写位(讲义原例)
起始信号后的第一个字节:高7位设备地址 + 最低1位读写位
-
0x10 =
0001 0000 → 设备地址0x10,0=写(主机发送数据给从机) -
0001 0001 (即0x11)→ 设备地址0x10,1=读(从机发送数据给主机)
即:写字节 = 设备地址<<1 | 0 ,读字节 = 设备地址<<1 | 1 。 讲义另一例:0xAC =
1010 1100= 0x59写、0x5D读(高位先行传输1010 110+ 方向位)。
二、I2C时序
I2C所有操作都由起始、数据传输、应答、结束四种信号组成:
1. 起始信号(Start)
SCL时钟线为高电平时,SDA数据线由高变低(下降沿)
SDA ────┐
└──────── ← SCL高电平期间SDA下降沿 = 起始
SCL ──────────────
由主机发出,表示一次传输开始。
2. 数据传输(有效性规则)
SCL为高电平时:SDA必须保持稳定,此时接收方采样数据
SCL为低电平时:SDA可以改变,此时发送方发送(更新)数据
1 0 1 0 1 1 0 0 ← 高位先行
SDA ─┐ ┌─┐ ┌─────┐
└─┘ └───┘ └──
SCL ──┐ ┌─┐ ┌─┐ ┌─┐ ┌──
└─┘ └─┘ └─┘ └─┘
↑每个SCL高电平采样一位
记忆:"高采样、低换数"------SCL高电平锁数据,低电平换数据。(只有起始/结束信号例外,故意在SCL高电平期间改变SDA来产生特殊标志。)
3. 应答信号(ACK / NACK)
每传输8位数据 后的第9个时钟周期,接收方需向发送方回复应答信号:
ACK:低电平(应答,收到了)
NACK:高电平(非应答)
发送方第9个时钟释放SDA(靠上拉变高),由接收方拉低(ACK)或保持高(NACK)。
4. 结束信号(Stop)
SCL时钟线为高电平时,SDA数据线由低变高(上升沿)
SDA ┌────────
───────────┘ ← SCL高电平期间SDA上升沿 = 结束
SCL ──────────────────
由主机发出,表示一次传输结束。
三、I2C写时序与读时序
1. i2c写时序(主机→从机写寄存器)
S + 设备地址+W → ACK → 寄存器地址 → ACK → 数据 → ACK → P
| 步骤 | 操作 |
|---|---|
| 1 | 主机发送起始信号 + 设备地址 + 写位(0),等待从机ACK |
| 2 | 主机发送寄存器地址,等待从机ACK |
| 3 | 主机发送数据(写入该寄存器),等待从机ACK |
| 4 | 主机发送停止信号 |
2. i2c读时序(主机←从机读寄存器)★i2c_read函数对应
| 步骤 | 操作 |
|---|---|
| 1 | 主机发送起始信号 + 设备地址 + 写位(0),等待从机ACK |
| 2 | 主机发送寄存器地址,等待从机ACK |
| 3 | 主机重发起始信号(Repeated Start)+ 设备地址 + 读位(1),等待从机ACK |
| 4 | 主机接收从机数据,主机回复ACK应答 |
| 5 | 接收最后一个字节 后,主机回复NACK(告诉从机不要再发) |
| 6 | 主机发送停止信号 |
为什么要"写转读"(Dummy Write) :读之前主机必须先用"写操作"告诉从机要读哪个寄存器(步骤1~2),再通过Repeated Start切换为读方向(步骤3),从机才知道从哪个寄存器把数据吐出来。 为什么最后是NACK:主机回NACK表示"我收够了",从机释放SDA,主机才能发出停止信号。