IIC通信协议详解(一篇文章搞懂I2C原理、时序与读写流程)
一、前言
在嵌入式开发过程中,单片机经常需要和各种外部设备进行数据交互。
例如:
STM32读取MPU6050传感器数据
STM32驱动OLED显示屏
EEPROM保存设备参数
温湿度传感器采集环境数据
这些设备之间想要通信,就需要一种“交流语言”,这就是通信协议。
常见的嵌入式通信协议有:
UART
SPI
IIC(I2C)
CAN
RS485
其中,IIC是一种非常经典的板级通信协议,在传感器、显示屏、存储芯片中应用非常广泛。
很多刚学习嵌入式的小伙伴第一次接触IIC时,会遇到几个问题:
SCL是什么?
SDA是什么?
为什么IIC只有两根线?
为什么需要上拉电阻?
ACK到底有什么作用?
IIC读写流程是什么?
本文将从硬件结构、通信时序以及实际读写流程三个方面,带大家完整理解IIC。
二、什么是IIC?
IIC全称:
Inter-Integrated Circuit
中文叫:
集成电路间通信总线。
IIC最早由飞利浦公司提出,现在已经成为嵌入式开发中非常常见的一种通信方式。
IIC最大的特点:
使用两根线完成通信
分别是:
| 名称 | 英文 | 作用 |
|---|---|---|
| SCL | Serial Clock | 时钟线 |
| SDA | Serial Data | 数据线 |
1. SCL时钟线
SCL负责产生时钟信号。
IIC属于同步通信。
所谓同步,就是:
通信双方按照统一的时间节奏进行数据传输。
这个节奏由SCL提供。
可以理解为:
SCL就是通信中的“节拍器”。
2. SDA数据线
SDA负责数据传输。
例如:
设备地址
寄存器地址
实际数据
全部通过SDA进行传输。
三、IIC通信结构
IIC采用:
一主多从结构
也就是说:
一个主机可以连接多个从设备。
例如:
STM32作为主机:
主机:
STM32
从设备:
OLED
MPU6050
EEPROM
所有设备共享同一组:
SCL线
SDA线
那么问题来了:
多个设备连接在一起,STM32如何知道当前要和哪个设备通信?
答案:
设备地址
每一个IIC设备都有自己的地址。
例如:
OLED:
0x3C
MPU6050:
0x68
EEPROM:
0x50
通信时:
STM32首先发送目标设备地址。
只有地址匹配的设备才会响应。
四、IIC硬件组成
一个完整的IIC通信,需要三个重要部分。
1. SCL时钟线
SCL由主机产生。
例如:
STM32作为主机时:
STM32输出时钟信号。
作用:
控制数据传输节奏。
2. SDA数据线
SDA是一根双向数据线。
发送数据:
MCU → 外设
读取数据:
外设 → MCU
所以SDA既可以发送,也可以接收。
3. 上拉电阻
这是IIC中非常重要的一个知识点。
为什么IIC需要上拉电阻?
因为:
IIC使用开漏输出结构。
设备只能主动拉低电平。
但是无法主动输出高电平。
因此需要外部上拉电阻,将信号拉到高电平。
常见上拉电阻:
4.7KΩ
作用:
保证总线空闲状态保持高电平。
如果没有上拉电阻,可能出现:
通信失败
波形异常
设备无法识别
五、IIC通信时序
一次完整的IIC通信过程如下:
START
↓
发送设备地址
↓
ACK应答
↓
数据传输
↓
ACK应答
↓
STOP
下面详细分析每一步。
六、START起始信号
通信开始之前:
主机需要发送START信号。
START产生条件:
当SCL保持高电平时:
SDA由高电平变为低电平。
也就是:
SDA:
1 → 0
表示:
开始一次IIC通信。
七、发送设备地址
START之后:
主机发送设备地址。
IIC通常采用:
7位地址 + 1位读写位
格式:
设备地址 + R/W
其中:
W=0
表示写操作。
例如:
STM32配置MPU6050寄存器。
R=1
表示读操作。
例如:
读取传感器数据。
八、ACK应答
IIC通信中:
每发送8bit数据后,需要等待设备回应。
这个回应就是:
ACK。
例如:
发送:
8位数据
第9个时钟:
设备返回ACK。
如果设备正常收到:
SDA拉低。
表示:
ACK成功。
如果没有响应:
就是NACK。
常见原因:
地址错误
设备未上电
接线错误
没有上拉
九、数据传输
地址确认之后:
开始传输真正的数据。
例如:
STM32向MPU6050写数据:
通信流程:
START
↓
MPU6050地址 + W
↓
ACK
↓
寄存器地址
↓
ACK
↓
数据
↓
ACK
↓
STOP
十、STOP结束信号
通信完成后:
主机发送STOP。
STOP条件:
SCL保持高电平:
SDA由低变高。
表示:
本次通信结束。
十一、IIC写数据流程
写数据是最常见的操作。
例如:
初始化传感器。
流程:
START
↓
设备地址 + W
↓
ACK
↓
寄存器地址
↓
ACK
↓
写入数据
↓
ACK
↓
STOP
实际开发中:
很多传感器初始化代码,本质上就是不断向寄存器写入配置。
十二、IIC读数据流程
读取数据相比写操作复杂一些。
例如:
读取MPU6050的数据。
通常需要两步。
第一步:
告诉设备读取哪个寄存器。
流程:
START
↓
设备地址 + W
↓
寄存器地址
第二步:
重新开始读取。
流程:
ReSTART
↓
设备地址 + R
↓
读取数据
↓
NACK
↓
STOP
完整流程:
START
↓
地址+W
↓
寄存器地址
↓
ReSTART
↓
地址+R
↓
数据
↓
NACK
↓
STOP
十三、IIC和SPI区别
| 项目 | IIC | SPI |
|---|---|---|
| 通信线 | 2根 | 4根以上 |
| 速度 | 较慢 | 较快 |
| 通信方式 | 半双工 | 全双工 |
| 设备选择 | 设备地址 | CS片选 |
| 优势 | 节省IO | 高速通信 |
简单理解:
IIC:
省线,适合传感器。
SPI:
速度快,适合高速设备。
十四、IIC常见问题
1. 为什么扫描不到设备?
常见原因:
① 地址错误
② SDA/SCL接反
③ 没有共地
④ 没有上拉电阻
⑤ 设备没有供电
2. 为什么一直没有ACK?
检查:
设备地址是否正确
硬件连接是否正确
电源是否正常
通信频率是否过高
十五、总结
IIC核心知识可以总结为:
1. 两根线
SCL:
负责时钟
SDA:
负责数据
2. 一个主机多个从机
设备通过地址区分。
3. 通信流程
START
↓
地址
↓
ACK
↓
数据
↓
ACK
↓
STOP
4. 读写区别
写:
地址+W
↓
寄存器
↓
数据
读:
地址+W
↓
寄存器
↓
ReSTART
↓
地址+R
↓
数据
IIC看似复杂,其实核心就是:
通过SCL提供时钟,通过SDA传输数据,再利用设备地址找到目标设备。
掌握IIC之后,后续学习STM32驱动OLED、MPU6050、EEPROM等外设都会轻松很多。
