I2C 总线入门指南

张开发
2026/4/3 15:12:52 15 分钟阅读
I2C 总线入门指南
目录1. 什么是 I2C2. 物理层3. 信号定义4. 数据传输格式5. 读写操作时序6. Linux 驱动中的 I2C 使用7. 附录关键参数速查表1. 什么是 I2CI2CInter-Integrated Circuit是一种串行通信总线由 Philips 公司于 1982 年开发。1.1 主要特点特性说明总线类型串行、同步、半双工信号线数量2 根SDA、SCL通信方式主从式Master-Slave设备寻址7 位或 10 位地址传输速度标准模式 100kbps快速模式 400kbps高速模式 3.4Mbps多设备支持同一总线可连接多个设备1.2 典型应用场景传感器数据采集EEPROM 存储芯片读写LCD/OLED 显示屏控制电源管理芯片配置音频编解码器配置2. 物理层2.1 硬件连接┌─────────────┐ ┌─────────────┐│ Master │ │ Slave ││ SDA │◄──────────────────►│ SDA ││ SCL │───────────────────►│ SCL ││ GND │───────────────────►│ GND ││ VCC │───────────────────►│ VCC │└─────────────┘ └─────────────┘│ │┌──┴──┐ ┌──┴──┐│ 4.7k│ │ 4.7k│└──┬──┘ └──┬──┘└──────────────┬─────────────────┘│VCC (3.3V 或 5V)2.2 电气特性参数值说明输出类型开漏Open-Drain设备只能拉低电平不能驱动高电平上拉电阻4.7kΩ - 10kΩ将信号线拉至高电平低电平范围0V - 0.3×VCC逻辑 0高电平范围0.7×VCC - VCC逻辑 13. 信号定义3.1 信号线信号全称功能方向SDASerial Data数据传输双向SCLSerial Clock时钟同步主设备输出3.2 数据线SDASCL 为高电平时SDA 必须保持稳定SCL 为低电平时SDA 允许变化3.3 起始和停止条件起始条件StartSCL 高电平时SDA 从高变低停止条件StopSCL 高电平时SDA 从低变高重复起始条件Repeated Start不发送 Stop直接发送新的 Start用于连续操作4. 数据传输格式4.1 数据帧结构Start → [设备地址W] → ACK → [寄存器地址] → ACK → [数据] → ACK → Stop4.2 设备地址字节格式┌───┬───┬───┬───┬───┬───┬───┬───┐│ A6│ A5│ A4│ A3│ A2│ A1│ A0│ R/W│├───┴───┴───┴───┴───┴───┴───┴───┤│ 7 位设备地址 │ 读写位 │└───────────────────────────────┘位名称说明A6-A0设备地址7 位从设备地址R/W读写控制0写1读4.3 OV5647 设备地址示例树莓派OV5647 的 7 位地址为 0x36SCCB_ID 引脚接地时操作计算方式结果字节写操作(0x36 1) | 00x6C读操作(0x36 1) | 10x6D4.4 应答信号ACK/NACK信号产生方电平说明ACK接收方低电平0成功接收数据NACK接收方高电平1未成功接收或传输结束5. 读写操作时序5.1 单字节写操作写入一个寄存器值的完整时序Start → [设备地址W] → ACK → [寄存器地址] → ACK → [数据] → ACK → Stop实际信号以 OV5647 写 0x300a0x56 为例传输内容 Start 0x6C ACK 0x30 ACK 0x0a ACK 0x56 ACK Stop(写命令) (地址高) (地址低) (数据)5.2 单字节读操作读取一个寄存器值需要两次传输第一次传输写寄存器地址Start → [设备地址W] → ACK → [寄存器地址] → ACK第二次传输读数据RepStart → [设备地址R] → ACK → [数据] → NACK → Stop实际信号以 OV5647 读 0x300a 为例第一次 Start 0x6C ACK 0x30 ACK 0x0a ACK(写命令) (寄存器高) (寄存器低)第二次 RepStart 0x6D ACK 0x56 NACK Stop(读命令) (读取的数据)5.3 连续写操作连续写入多个数据字节部分设备支持地址自动递增Start → [设备地址W] → ACK → [寄存器地址] → ACK → [数据 1] → ACK → [数据 2] → ACK → ... → StopOV5647 配置示例向 0x300a 开始连续写 2 字节Start → 0x6C → ACK → 0x30 → ACK → 0x0a → ACK → 0x56 → ACK → 0x47 → ACK → Stop(寄存器 0x300a) (数据 1:0x300a) (数据 2:0x300b)地址自动递增注意并非所有设备都支持地址自动递增。写入不同寄存器地址时需要分别发送完整的地址 数据方法 1两次独立的 I2C 传输Start → [地址W] → ACK → [寄存器 A 地址] → ACK → [数据 A] → ACK → StopStart → [地址W] → ACK → [寄存器 B 地址] → ACK → [数据 B] → ACK → Stop方法 2使用 Repeated Start推荐Start → [地址W] → ACK → [寄存器 A 地址] → ACK → [数据 A] → ACK → RepStart→ [地址W] → ACK → [寄存器 B 地址] → ACK → [数据 B] → ACK → StopOV5647 配置示例分别写入 0x300a 和 0x300cStart → 0x6C → ACK → 0x30 → ACK → 0x0a → ACK → 0x56 → ACK → RepStart(0x300a) (0x56)→ 0x6C → ACK → 0x30 → ACK → 0x0c → ACK → 0x12 → ACK → Stop(0x300c) (0x12)5.4 时序参数参数标准模式 (100kbps)快速模式 (400kbps)时钟周期 t(SCL)≥10μs≥2.5μsStart 建立时间 t(SU;STA)≥4.7μs≥0.6μsStart 保持时间 t(HD;STA)≥4.0μs≥0.6μsSDA 建立时间 t(SU;DAT)≥250ns≥100nsSDA 保持时间 t(HD;DAT)≥0ns≥0nsStop 建立时间 t(SU;STO)≥4.7μs≥0.6μs总线空闲时间 t(BUF)≥4.7μs≥1.3μs6. Linux 驱动中的 I2C 使用6.1 数据结构Linux 内核提供 struct i2c_msg 描述一次 I2C 传输struct i2c_msg {__u16 addr; // 从设备地址7 位__u16 flags; // 传输标志__u16 len; // 数据长度字节__u8 *buf; // 数据缓冲区指针};flags 常用值0写操作I2C_M_RD0x0001读操作6.2 写寄存器函数示例static int i2c_write_register(struct i2c_client *client, u16 reg, u8 val){u8 buf[3];struct i2c_msg msg;buf[0] (reg 8) 0xff;buf[1] reg 0xff;buf[2] val;msg.addr client-addr;msg.flags 0;msg.len 3;msg.buf buf;return i2c_transfer(client-adapter, msg, 1);}6.3 读寄存器函数示例static int i2c_read_register(struct i2c_client *client, u16 reg, u8 *val){u8 buf[2];struct i2c_msg msg[2];buf[0] (reg 8) 0xff;buf[1] reg 0xff;msg[0].addr client-addr; msg[0].flags 0; msg[0].len 2; msg[0].buf buf;msg[1].addr client-addr; msg[1].flags I2C_M_RD; msg[1].len 1; msg[1].buf buf;int ret i2c_transfer(client-adapter, msg, 2);if (ret 2) { *val buf[0]; return 0; }return ret 0 ? ret : -EIO;}6.4 简化 APIi2c_smbusi2c_smbus_write_byte_data(client, reg, val); // 写 8 位i2c_smbus_read_byte_data(client, reg); // 读 8 位i2c_smbus_write_word_data(client, reg, val); // 写 16 位i2c_smbus_read_word_data(client, reg); // 读 16 位6.5 设备树配置i2c1 {status okay;ov5647: camera36 {compatible ovti,ov5647;reg 0x36;clocks camera_clk;pwdn-gpios gpio 5 0;};};7. 附录关键参数速查表7.1 I2C 地址计算7 位地址写字节读字节0x360x6C0x6D0x370x6E0x6F0x480x900x910x500xA00xA1计算公式写字节 (7 位地址 1) | 0读字节 (7 位地址 1) | 17.2 常用速度模式模式时钟频率应用场景标准模式 (Standard)100kbps传感器、EEPROM快速模式 (Fast)400kbps大多数 I2C 设备高速模式 (High-Speed)3.4Mbps高速 ADC/DAC7.3 常见错误码错误码含义可能原因0成功--ENXIO无设备响应设备地址错误、设备未供电-EIO通信错误总线干扰、时序问题-ETIMEDOUT超时SCL 被拉低、总线死锁7.4 调试命令# 扫描 I2C 总线上的设备i2cdetect -y 1# 读取寄存器值i2cget -y 1 0x36 0x30# 写入寄存器值i2cset -y 1 0x36 0x30 0x56

更多文章