ARM(10) - I2C
IIC:半双工同步串行通信方式 ---主从应答
一、IIC 的核心硬件组成
IIC 通信仅依赖两条总线,所有设备(主设备、从设备)的同名引脚均并联在这两条总线上,硬件结构极简:
信号线 | 名称 | 功能描述 |
---|---|---|
SDA | Serial Data(串行数据) | 双向数据线,用于主从设备之间传输数据(地址、命令、数据字节)。 |
SCL | Serial Clock(串行时钟) | 单向时钟线,由主设备产生,用于同步 SDA 线上的数据传输(控制数据采样时机)。 |
此外,硬件上需满足两个关键要求:
- 上拉电阻:SDA 和 SCL 均采用开漏输出(Open-Drain) 结构,必须通过外部上拉电阻(通常为 4.7kΩ~10kΩ)连接到电源(如 VCC),才能实现 “高电平” 输出(开漏输出本身只能拉低电平,无法主动输出高电平)。
- 总线电容限制:总线上所有设备的引脚电容之和需≤400pF(标准模式),否则会影响信号完整性(可通过缩短布线长度、减少设备数量优化)。
线与特性: 当总线上的引脚输出高电平时,总线上的电平高低由通信中的对方决定
总线闲时为高: 可抢占总线(高低电平可被改变)
二、IIC 的主从通信机制
IIC 采用 “主从(Master-Slave)” 架构,通信由主设备主动发起,从设备被动响应,核心规则如下:
1. 主设备与从设备的角色
主设备(Master):
- 唯一的时钟发生器(控制 SCL 的高低电平切换);
- 发起通信(产生 “起始条件”)和终止通信(产生 “停止条件”);
- 通过 “从设备地址” 选择要通信的从设备;
- 决定数据传输的方向(主→从,或从→主)。
- 典型设备:单片机(如 STM32、Arduino)、微处理器(如 Raspberry Pi)。
从设备(Slave):
- 无时钟产生能力,仅跟随 SCL 的时钟节奏采样 / 发送数据;
- 每个从设备都有唯一的7 位 / 10 位地址(由芯片硬件定义或软件配置),用于被主设备识别;
- 仅在被主设备选中后,才会响应数据传输。
- 典型设备:传感器(如温湿度传感器 SHT30)、EEPROM(如 AT24C02)、OLED 显示屏(如 SSD1306)。
2. 多设备支持
由于 SDA/SCL 总线并联,IIC 总线可挂载多个设备,但需满足:
- 所有从设备的地址唯一不重复(地址冲突会导致通信失败);
- 支持 “多主设备”(如两个单片机同时作为主设备),但需通过 “总线仲裁” 机制避免冲突(实际应用中较少见,通常仅单主设备)。
三、IIC 的通信协议流程(核心 时序)
IIC 的通信过程严格遵循 “起始条件 → 地址传输 → 数据传输 → 停止条件” 的时序逻辑,每个环节的 SDA/SCL 电平变化都有明确规定。
1. 起始条件(Start Condition,S)
主设备发起通信的 “信号”,标志着一次 IIC 通信的开始:
- 时序要求:当 SCL 为高电平时,SDA 从高电平跳变为低电平(即 “SCL 高→SDA 下拉”)。
- 作用:通知总线上所有从设备 “准备接收数据”,并复位所有从设备的接收状态机。
2. 地址传输(Slave Address + R/W Bit)
起始条件后,主设备首先发送8 位数据,用于选择从设备并指定数据方向:
- 前 7 位:从设备地址(最常见的是 7 位地址,10 位地址用于需要更多设备的场景);
- 第 8 位:读 / 写控制位(R/W):
0
:写操作(主设备→从设备传输数据,如向 EEPROM 写数据);1
:读操作(从设备→主设备传输数据,如从传感器读测量值)。关键响应:ACK/NACK
IIC 采用 “应答(ACK)” 机制确保数据传输可靠:
- 当主设备发送完 8 位地址后,会释放 SDA 总线(变为高电平),并拉低 SCL(进入 “应答检测周期”);
- 从设备:若地址匹配,会在 SCL 低电平时将 SDA 拉低(输出 “ACK”),并在 SCL 高电平时保持低电平(主设备采样到低电平,确认从设备已选中);
- 若地址不匹配,从设备不会拉低 SDA(SDA 保持高电平,即 “NACK”),主设备会终止此次通信。
3. 数据传输(Data Bytes)
地址确认后,进入数据传输阶段,每次传输1 字节(8 位),且每字节后必须跟随 1 个 ACK/NACK:
- 数据采样时机:SCL 为高电平时,SDA 线上的数据必须保持稳定(主 / 从设备在此刻采样数据);
- 数据变化时机:SCL 为低电平时,SDA 线上的数据才能发生变化(避免主从采样到不稳定的 “毛刺”);
- 方向由 R/W 位决定:
- 写操作(R/W=0):主设备连续发送数据字节,从设备每接收 1 字节后回复 ACK;
- 读操作(R/W=1):从设备连续发送数据字节,主设备每接收 1 字节后回复 ACK(若主设备不需要更多数据,可回复 NACK,通知从设备停止发送)。
4. 停止条件(Stop Condition,P)
主设备终止通信的 “信号”,标志着一次 IIC 通信的结束:
- 时序要求:当 SCL 为高电平时,SDA 从低电平跳变为高电平(即 “SCL 高→SDA 上拉”);
- 作用:通知所有从设备 “通信结束”,总线释放,可准备下一次通信。
5.图文总结
MSB高位先行
发送数据:SCL 高电平不能切换----真正在通信
start和stop:在时钟SDL高电平时,产生一个下降沿或一个上升沿
(1)start信号:在时钟线为高电平时,数据线产生一个下降沿
(2)总线规定:
(0)IIC数据发送MSB先行;
(1)当时线为低电平时,数据线允许发送方改变,不允许接收方采样。
(2)当时钟线为高电平时,数据线不允许发送方改变,允许接收方采样。(3)应答位:
(1)ACK应答:低电平
(2)NACK非应答:高电平(4)stop信号:在时钟线为高电平时,数据线产生一个上升沿
从机地址:
从机设备在总线中的唯一编号数据流向位:
0:接下来的数据主机发,从机收。---write
1:接下来的数据主机收,从机发。---read
地址范围:AT24C02 仅 256 字节,地址不可超过 0xFF,否则会 “回卷” 到 0x00 地址(覆盖原有数据)
四、AT24C02 EEPROM IIC 通信准备知识
1. 核心对象 ——AT24C02 芯片简介
- 芯片类型:AT24C02 是一款基于 IIC 总线的EEPROM(电可擦除可编程只读存储器),用于掉电后数据不丢失的存储(如存储设备参数、用户配置等);
- 容量规格:2K 位(即 256 字节,地址范围 0x00~0xFF),支持字节写、页写(1 次最多写 8 字节)、随机读、连续读等操作;
- 供电范围:通常 2.5V~5.5V,兼容多数 MCU 的 3.3V/5V 供电;
- 从机地址:默认前 4 位固定为 1010(即 0xA),后 3 位由芯片 A2、A1、A0 引脚电平决定(通常硬件接 GND,即 A2A1A0=000),因此:
- 写操作地址:0xA0(10100000,第 8 位为 0);
- 读操作地址:0xA1(10100001,第 8 位为 1)。
A------民用级
02-----2K个·bit ---------256个字节
EEPROM:电可擦除可编程只读存储器
- 页写边界:若用 “页写函数”(一次写 8 字节),需确保写入地址在同一页(如 0x00~0x07 为第 1 页,0x08~0x0F 为第 2 页),跨页写会覆盖前面数据;
2.通信时序图
1、地址
write-- 0 --主机发 --》 从机收
read-- 1 --从机发 --》 主机收
2、 写
页写
3、读
write-- 0 --主机发 --》 从机收
read-- 1 --从机发 --》 主机收
读多个字节
所有start stop信号都是主机发的
3. IIC硬件引脚与连接
AT24C02 引脚 | 功能 | 连接到 IMAX6ULL引脚 |
---|---|---|
VCC | 电源 | 3.3V |
GND | 地 | GND |
SDA | 串行数据线 | P4 --42 |
SCL | 串行时钟线 | P4 --43 |
(注:SDA/SCL 引脚需配置为 STM32 的 “开漏输出模式”,符合 IIC 总线的线与特性;若使用 MCU 的硬件 IIC 外设,需对应配置外设时钟)
4.查手册
5.注意事项
- EEPROM 写周期:
AT24C02 写完数据后,内部需要时间完成 “电擦除 - 编程”,必须等待≥5ms 再读,否则读的是旧数据或乱码;
- 页写边界:
若用 “页写函数”(一次写 8 字节),需确保写入地址在同一页(如 0x00~0x07 为第 1 页,0x08~0x0F 为第 2 页),跨页写会覆盖前面数据;
- 地址范围:
AT24C02 仅 256 字节,地址不可超过 0xFF,否则会 “回卷” 到 0x00 地址(覆盖原有数据);
- 总线冲突:
若总线上接多个从机,需确保每个从机的 A2A1A0 引脚配置不同,避免地址冲突。
五、实现代码
i2c.c
写 write
读 read
main.c
六、IIC 的优缺点
优点:
- 布线极简:仅需 2 条线,大幅减少 PCB 板空间和布线复杂度(对比 SPI 的 4 条线更优);
- 多设备支持:单总线可挂载多个从设备,无需片选线(通过地址区分);
- 双向通信:SDA 为双向线,主从设备可灵活切换数据传输方向;
- 硬件成本低:无需额外通信芯片,仅需上拉电阻,成本极低。
缺点:
- 速率较低:最高速率(3.4 Mbps)远低于 SPI(可达几十 Mbps),不适合高速数据传输(如图像、音频);
- 抗干扰差:SDA/SCL 为开漏总线,电平变化较慢,易受电磁干扰(需注意布线屏蔽);
- 总线负载有限:总线上设备数量和电容受限制,无法挂载过多设备;
- 协议较复杂:相比 UART(仅需 TX/RX),IIC 的时序(起始 / 停止、ACK、地址)更复杂,软件实现需严格遵循协议。
七、典型应用场景
IIC 因低速、简布线的特点,广泛用于以下场景:
- 存储芯片:EEPROM(如 AT24C 系列)、FRAM(铁电存储器);
- 传感器:温湿度传感器(SHT30、DHT12)、光照传感器(BH1750)、加速度传感器(ADXL345);
- 显示模块:OLED 显示屏(SSD1306)、LCD1602(带 IIC 转接板);
- 电源管理:PMIC(电源管理芯片,如 TI 的 TPS65217);
- 其他:实时时钟(RTC,如 DS3231)、ADC/DAC(如 ADS1115)。
总结
IIC 是一种 “低成本、低速率、多设备” 的串行通信协议,核心优势在于极简的硬件布线和灵活的主从通信机制,适合中低速外设的短距离数据交互。其关键是理解SDA/SCL 的时序逻辑(起始 / 停止条件、ACK 应答、数据采样时机)和主从角色分工,这是软件实现 IIC 通信(如 STM32 的 HAL 库、Arduino 的 Wire 库)的基础。
1. 简述线与特性是什么
当总线上的引脚输出高电平时,总线上的电平高低,由通信新中的对方决定
IIC 总线仅需两根线(SDA:串行数据线、SCL:串行时钟线),其 “线与” 特性是多设备共总线的核心基础,本质由 “开漏输出 + 上拉电阻” 硬件结构决定,具体规则如下:
- 核心逻辑:总线电平由 “所有设备的输出状态” 共同决定 ——
- 若任意一个设备将 SDA/SCL 线拉低(输出低电平),则总线整体为低电平;
- 仅当所有设备都释放总线(输出高阻态,相当于 “不驱动”),总线才会被上拉电阻拉回高电平。
- 关键作用:
- 支持 “多主设备”:多个主设备可同时尝试控制总线,通过 “线与” 特性避免电平冲突(若两个主设备分别发高、低,总线最终为低,不会出现短路);
- 简化从设备设计:从设备无需主动输出高电平,仅需在需要时拉低总线(如应答信号),释放后由上拉电阻自动恢复高电平。
2. start信号与stop信号是什么样的
Start 和 Stop 信号均由主设备主动生成,是 IIC 通信 “开始 / 结束” 的标志,核心区别在于 SDA 线在 SCL 高电平时的跳变方向(SCL 是时钟线,高电平时总线电平需稳定,因此跳变仅在 SCL 高电平时发生):
信号类型 波形特征(SCL 与 SDA 的配合) 作用 Start 信号(S) 1. 先保持 SCL 为高电平;
2. SDA 线从 “高电平” 跳变为 “低电平”(下降沿);
3. 随后 SCL 可拉低,进入数据传输阶段。告知总线上所有从设备:“通信即将开始,请准备接收从设备地址”。 Stop 信号(P) 1. 先保持 SCL 为高电平;
2. SDA 线从 “低电平” 跳变为 “高电平”(上升沿);
3. 之后 SCL 可释放(拉高),总线回归空闲状态。告知所有从设备:“本次通信结束,总线释放”。 注:空闲状态下,SDA 和 SCL 均为高电平(由上拉电阻维持)。
3. 简述 IIC 通信的完整时序
1、主设备写从设备时序(主→从发数据)
主设备向从设备传输数据(如配置从设备寄存器、发送控制指令),全程由主设备控制 SDA 数据方向,从设备仅负责 “地址应答” 和 “数据应答”,步骤如下:
Step 1:发起 Start 信号(S)
- 总线空闲时(SDA、SCL 均为高),主设备先保持 SCL 为高,再将 SDA 从 “高→低”(下降沿),生成 Start 信号;
- 作用:告知所有从设备 “通信开始,准备接收地址”。
Step 2:发送 “从设备地址 + 读写位”(8 位)
- 前 7 位:目标从设备的唯一地址(IIC 协议规定,用于筛选总线上的特定从设备);
- 第 8 位(R/W 位):0(表示 “主写从”,数据方向为主→从);
- 同步规则:SCL 低电平时,主设备更新 SDA 电平(准备 1bit 数据);SCL 高电平时,从设备采样 SDA 电平(读取 1bit 数据)—— 确保数据稳定时采样,避免误读。
Step 3:从设备发送地址应答(ACK)
- 第 8 位数据传输结束后,SCL 拉低,主设备释放 SDA(变为高阻态,交出 SDA 控制权);
- 若从设备识别到自身地址,会在 SCL 再次变高时,将 SDA 拉低(输出低电平),表示 “地址匹配,准备接收数据”(ACK);
- 若从设备未识别地址,则不拉低 SDA(总线保持高,即 NACK),主设备需终止通信。
Step 4:主设备逐字节发数据 + 从设备数据应答
- 主设备重新控制 SDA,按 “Step 2” 的同步规则,逐字节(8bit / 字节)向从设备发送数据(如寄存器值、指令);
- 每发送 1 字节后,重复 “Step 3” 的应答逻辑:从设备需发 ACK(拉低 SDA)表示 “数据接收成功”,若从设备缓存满 / 接收错误,发 NACK,主设备停止数据发送。
Step 5:发起 Stop 信号(P)
- 数据传输完成后,主设备先将 SCL 拉回高,再将 SDA 从 “低→高”(上升沿),生成 Stop 信号;
- 作用:告知从设备 “通信结束”,主从设备释放总线,SDA、SCL 回归高电平(空闲态)。
2、主设备读从设备时序(从→主发数据)
主设备主动读取从设备的数据(如传感器采集值、寄存器状态),核心差异是:地址阶段后,数据方向变为 “从→主”,应答方从 “从设备” 变为 “主设备”,步骤如下:
Step 1:发起 Start 信号(S)
与 “主写从” 完全一致:SCL 高时,SDA 高→低,触发 Start。Step 2:发送 “从设备地址 + 读写位”(8 位)
- 前 7 位:仍为目标从设备地址(与主写从相同);
- 第 8 位(R/W 位):1(表示 “主读从”,数据方向为从→主);
- 同步规则不变:SCL 低电平时主设备更 SDA,SCL 高时从设备采样。
Step 3:从设备发送地址应答(ACK)
与 “主写从” 一致:从设备识别地址后,在 SCL 高时拉低 SDA(ACK),表示 “准备发送数据”;未识别则发 NACK,主设备终止通信。Step 4:从设备逐字节发数据 + 主设备数据应答
- 从设备控制 SDA,按 “同步规则” 逐字节向主设备发送数据(如传感器值);
- 每接收 1 字节后,主设备负责应答:
- 若主设备需继续读取下一字节:在 SCL 高时拉低 SDA(ACK),告知从设备 “继续发”;
- 若主设备已读取所有所需数据(如最后 1 字节):主设备不拉低 SDA(发 NACK),告知从设备 “无需再发数据”—— 这是避免从设备持续发数据的关键逻辑。
Step 5:发起 Stop 信号(P)
与 “主写从” 一致:SCL 高时,SDA 低→高,生成 Stop,释放总线。