I²C
简介
集成电路总线(Inter-Integrated Circuit)是一种串行协议(通常缩写为 I²C 或 I2C),它允许多个外围芯片(slave)与一个或多个控制器芯片(master)进行通信。多个设备可以连接到同一条 I²C 总线,并且可以通过指定其 I²C 地址将消息发送到特定设备。该协议需要两根信号线,只能用于设备内的短距离通信。
其中一根信号线用于数据(SDA),另一根用于时钟信号(SCL)。默认情况下,线路被总线上某处的电阻拉高。总线上的任何设备(甚至同时有多个设备)可以“拉低”一条或两条信号线。这意味着如果两个设备同时尝试在总线上通信,电路并不会发生损坏——只有发送的消息会损坏(并且可以检测到)。
I²C 事务由一条或多条消息组成。每条消息都包含一个起始信号、一些字,最后是一个结束信号(如果有后续消息,则为另一个起始信号)。每个字都是八位,后面跟着一个 ACK(0)或 NACK(1)位,由接收方发送,以指示是否正确接收和理解该字。第一个字指示此消息的目标设备的 7 位地址,以及表示要从设备读取还是写入的位。如果总线上没有具有此地址的设备,第一个字后面自然会得到一个 NACK(因为没有设备将 SDA 线驱动为低电平以生成 ACK 位),于是你就可以知道此设备不存在。
SCL 上的时钟频率通常为 400 kHz,但也支持更慢和更快的速度(标准速度为 100 kHz-400 kHz-1 MHz)。在我们的练习中,将配置为 400 kHz(<MasterConfig as Default>::default().baudrate(400.kHz().into())
)。
要从 EEPROM 设备读取三个字节,通信序列将类似于:
步骤 | 控制器发送 | 外设发送 |
---|---|---|
1. | 起始信号 | |
2. | 设备地址 + 写 | |
3. | ACK | |
4. | 高位 EEPROM 地址字节 | |
5. | ACK | |
6. | 低位 EEPROM 地址字节 | |
7. | ACK | |
8. | 起始信号 | |
9. | 设备地址 + 读 | |
10. | ACK | |
11. | EEPROM 地址上的数据字节 | |
12. | ACK | |
13. | EEPROM 地址 +1 上的数据字节 | |
14. | ACK | |
15. | EEPROM 地址 +2 上的数据字节 | |
16. | NAK(即结束读取) | |
17. | 结束信号 |
I²C 信号图
I²C 总线上的数据传输时序图:
- S - 起始条件
- P - 结束条件
- B1 到 BN - 传输一位数据
- 当 SCL 为低电平(蓝色)时允许 SDA 电平变化,否则将生成起始或结束条件。