🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习
🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发
❄️作者主页:一个平凡而乐于分享的小比特的个人主页
✨收录专栏:通信协议,本专栏为记录项目中用到的知识点,以及一些硬件常识总结
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

I²C通信协议详解
第一章:I²C协议介绍
1.1 I²C协议简介
I²C(Inter-Integrated Circuit,集成电路总线)是一种简单、双向、同步的串行通信总线,由飞利浦公司在1980年代开发。它只需要两根线就能在多个设备间进行通信。
核心特性:
- 两线制:SDA(数据线)和SCL(时钟线)
- 多主多从:支持多个主设备和从设备
- 地址寻址:每个从设备有唯一地址
- 低速传输:适合短距离、低速设备通信
物理连接示意图:
主设备1 主设备2
│ │
└─────┬─────┘
│
┌──┴──┐
│总线 │
└──┬──┘
│
┌─────┼─────┐
从设备1 从设备2 从设备3
1.2 I²C设备地址
每个I²C从设备都有一个7位或10位的硬件地址。主设备通过发送这个地址来选择要通信的从设备。
7位地址格式:
┌─────┬─────────────────────────────────────┐
│ 位 │ 7 6 5 4 3 2 1 0 │
├─────┼─────────────────────────────────────┤
│ 含义 │ A6 A5 A4 A3 A2 A1 A0 R/W │
└─────┴─────────────────────────────────────┘
- A6-A0:7位设备地址
- R/W:读写标志位(0=写,1=读)
常用设备地址示例:
| 设备类型 | 典型地址(十六进制) | 地址(二进制) |
|---|---|---|
| EEPROM | 0x50 | 1010000 |
| 温度传感器 | 0x48 | 1001000 |
| 实时时钟 | 0x68 | 1101000 |
| OLED显示屏 | 0x3C | 0111100 |
地址分配表:
地址范围 用途
0000 000 广播地址
0000 001 起始字节
0000 010 CBUS地址
0000 011 保留
0000 1XX 高速模式
1111 0XX 保留
1111 1XX 10位地址标识
0001 000-1110 111 7位设备地址(可用112个)
第二章:I²C通信时序
2.1 起始位和停止位
起始条件(START):
- SCL为高电平 时,SDA从高电平跳变到低电平
- 表示开始一次新的通信
停止条件(STOP):
- SCL为高电平 时,SDA从低电平跳变到高电平
- 表示结束当前通信

2.2 I²C读写地址
I2C的读写地址除了 7bit 物理地址以外,还有 1bit 用来标识读/写方向位。这样I2C的从设备读写地址通常是一个字节,其中高 7bit 是上面描述的物理地址,最低位用来表示读写方向(0 为写操作,1为读操作)。

2.3 I²C应答信号
每个字节传输后,接收方必须发送一个应答位:
- ACK(应答):SDA被拉低
- NACK(非应答):SDA保持高电平

2.4 数据位收发
数据位传输规则:
- SCL为低电平时,SDA可以改变状态
- SCL为高电平时,SDA必须保持稳定
- 数据按高位先传(MSB First)

2.5 总线速率
I²C支持多种速度模式:
| 模式 | 速率 | 用途 |
|---|---|---|
| 标准模式 | 100 kbps | 通用低速设备 |
| 快速模式 | 400 kbps | 大多数传感器 |
| 快速模式+ | 1 Mbps | 高速需求 |
| 高速模式 | 3.4 Mbps | 特殊高速设备 |
速率对比示意图:
速率 (kbps)
3500 ┤ ╭─高速模式
3000 ┤ │
2500 ┤ │
2000 ┤ │
1500 ┤ │
1000 ┤ ╭─快速模式+ │
500 ┤ │ │
400 ┤ ╭─快速模式│ │
200 ┤ │ │ │
100 ┤╭─标准模式 │ │
0 └┴──────┴─────────┴───────────────────┘
2.6 主机发送数据流程
完整写操作流程:
主设备(发送数据到从设备)
步骤1:发送起始条件
步骤2:发送从设备地址 + 写标志(0)
步骤3:等待从设备应答(ACK)
步骤4:发送数据字节1
步骤5:等待从设备应答
步骤6:发送数据字节2
步骤7:等待从设备应答
...
步骤N:发送停止条件

2.7 主机接收数据流程
完整读操作流程:
主设备(从从设备读取数据)
步骤1:发送起始条件
步骤2:发送从设备地址 + 读标志(1)
步骤3:等待从设备应答(ACK)
步骤4:接收数据字节1
步骤5:发送应答(ACK)
步骤6:接收数据字节2
步骤7:发送应答(ACK)
...
步骤N:接收最后一个字节
步骤N+1:发送非应答(NACK)
步骤N+2:发送停止条件

第三章:I²C实战应用
场景示例:智能气象站
假设我们有一个智能气象站,包含以下I²C设备:
- 温度传感器(地址0x48)
- 湿度传感器(地址0x5C)
- 气压传感器(地址0x77)
- OLED显示屏(地址0x3C)
系统连接图:
┌─────────────────┐
│ 主控制器 │
│ (STM32) │
└────────┬────────┘
│
SDA ──┼────┬────────┬────────┬────────┐
SCL ──┼────┼────────┼────────┼────────┘
│ │ │ │
┌────────┴┐ ┌─┴─────┐ ┌─┴─────┐ ┌─┴─────┐
│温度传感器│ │湿度传感器│ │气压传感器│ │OLED屏│
│ 0x48 │ │ 0x5C │ │ 0x77 │ │ 0x3C │
└─────────┘ └───────┘ └───────┘ └───────┘
读取温度数据的代码逻辑(伪代码):
c
// 1. 发送起始信号
i2c_start();
// 2. 发送温度传感器地址 + 写位
i2c_send_byte(0x48 << 1 | 0); // 0x48左移1位,最后一位0表示写
// 3. 检查ACK
if (i2c_check_ack()) {
// 4. 发送要读取的寄存器地址
i2c_send_byte(TEMP_REGISTER);
// 5. 发送重新开始信号
i2c_restart();
// 6. 发送温度传感器地址 + 读位
i2c_send_byte(0x48 << 1 | 1); // 最后一位1表示读
// 7. 读取温度数据(2字节)
uint8_t temp_high = i2c_read_byte();
i2c_send_ack(); // 发送ACK,继续读取
uint8_t temp_low = i2c_read_byte();
i2c_send_nack(); // 发送NACK,最后一个字节
// 8. 发送停止信号
i2c_stop();
// 9. 处理数据
float temperature = process_temp_data(temp_high, temp_low);
}
第四章:常见问题与调试技巧
问题排查表:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 无应答 | 1. 地址错误 2. 设备未上电 3. 线路故障 | 1. 检查地址 2. 检查电源 3. 检查连接 |
| 数据错误 | 1. 总线竞争 2. 时钟太快 3. 干扰 | 1. 检查多主冲突 2. 降低速率 3. 添加滤波 |
| 总线锁死 | SCL被长期拉低 | 发送9个以上时钟脉冲 |
调试工具推荐:
- 逻辑分析仪:直观查看波形
- I²C扫描工具:自动发现设备地址
- 示波器:测量信号质量
- 软件调试:逐步执行通信过程
总结
I²C协议以其简洁的两线设计和灵活的寻址机制,成为嵌入式系统中最常用的通信协议之一。通过掌握起始/停止条件、地址寻址、数据收发流程和应答机制,您可以轻松实现各种I²C设备的控制。
记住关键点:
- 两根线:SDA(数据)和SCL(时钟)
- 地址优先:先发地址,再发数据
- 应答必需:每个字节后都有ACK/NACK
- 时钟同步:数据在SCL低时变化,高时稳定
- 速率可选:根据设备能力选择合适的速率
通过实际项目的练习,您将能熟练运用I²C协议连接各种传感器、存储器和显示设备。