Linux下I2c总线协议系列(一)i2c的概念以及i2c协议
在常规开发工作中,在涉及IC与其间的通信非常频繁的情况下(即硬件中采用多种总线BUS),会将不同外设的IC通过总线连接至中央处理器CPU以实现对它们的操作作用。其中,I2C(totality)无疑是最为广泛、操作最为简便的一种数据传输接口,其核心优势在于无需复杂的电平转换电路,并且支持双端模式的数据传输特性使其成为工业领域中的主流选择之一,值得深入探讨其工作原理及应用方法。希望编写一个系列文章来系统地阐述I2C(totality)的工作原理以及如何将其抽象化和编程实现
该篇文章旨在向大家提供关于I2C的基本认识,并非深入的技术讲解。在讲解Linux编程时会对此进行具体抽象处理。
I2C的概念即为inter-integrated circuit其对应的中文译名是片内串行总线由一条用于传输数据的SDA线和一条用于传输时钟信号的SCL线路组成
I2C的特性characteristic
a、是一种半双工通讯的总线协议
b、在i2c总线上,主机与从端、发送端与接收端的关系并非固定不变,而是受当前数据传输方向的影响。
下图是I2C总线,在硬件原理图当中大概的连接。

二、I2c总线的协议和时序图Timing chart
I2C协议是一种用于设备间高效通信的接口标准。
该接口包含两条双向通信通道,并采用大端模式进行数据传输。
其中一条为数据线(SDA),另一条为时钟线(SCL)。
采用大端模式进行数据传输的方式下,每次传递的数据量为8位。
值得注意的是,在实际应用中需要确保设备间的总线电压兼容性,并定期对总线上可能出现的寄生电容进行测量。
该协议的特点在于能够实现多主控设备的同步操作,并规定在任何时间段内仅允许一个主控执行操作。
每个设备都拥有独特的地址标识。这些标识由七个二进制位组成,并且当广播信号发送时所有位会被设为零值(0)。该设备的地址占用七位二进制数,并且具有唯一性。为了完成操作任务需要访问的是IC芯片上的寄存器单元。因此另有一个寄存器地址域(Register Address Field)占用八位二进制数。(下面将介绍I2C总线的读写过程)
系统内可能存在多个相同类型的芯片。因此addr被划分为固定部分和可编程部分。这些划分取决于芯片的具体性质。为了获得详细信息,请参考数据手册。
1.1 I2C位传输协议
数据传输:当SCL处于高电平时,SDA线若保持恒定,则用于传输数据bit;
当SDA线发生突变时,则用于表示一个会话的开始或结束(后续讨论);
数据改变:只有在SCL处于低电平状态时,SDA线才能完成对传输bit值的更改。

本节将介绍I2C协议中用于启动和终止通信的信号。
在I2C协议中:
- 开始信号:当SCL处于高电平时(H),SDA由H变为L以发送数据。
- 结束信号:当SCL持续处于高电平时(H),SDA由L恢复为H以完成数据接收。

1.3 I2C应答信号
Master在发送完8bit数据后响应Slave。

I2C写流程
按标准程序组织的写寄存器流程如下:
- Master发送一个START命令
- Master输出一个包含7位地址码和一个1位写操作指示(0)的数据包,并等待确认
- Slave端接收到该数据包后回复ACK
- Master输出包含8位有效数据的读取指令,并等待确认
- Slave端接收到该指令后回复ACK
- Master向Slave传输一组8位数据单元,并等待确认
- Slave端接收到该数据后回复ACK
- 步骤6至7可循环执行多次以连续更新多个寄存器值
- 最后Master发送一个STOP指令以结束整个操作流程
写一个寄存器

写多个寄存器

1.5 I2C读流程
读寄存器的标准流程如下:
1. 主设备通过I2C总线传输7位地址码,并同步执行写入操作一。
2. 从设备接收至状态确认的ACK信号。
3. 主设备向从设备传输8位地址码并等待响应。
4. 从设备接收至主设备的ACK确认信号。
5. 启动程序启动标志设置到位。
6. 主设备再次向从设备传输7位地址码及读回操作一。
7. 从 devices 接收至主 devices 的读回确认信号ack.
8. 将8位数据返回给主 device 作为当前 register 存储值的结果。(此步骤可与步骤9组合循环执行以读取多个 register)
9. 主 device 接收至状态确认信号ack.
读一个寄存器

读多个寄存器

本文参考博客:
下一篇打算分析,I2c总线在Linux编程中的代码实现。
