IIC通讯协议(Inter-Integrated Circuit,也常被写作I2C)是由 Philips 公司开发的一种简单、双向二线制同步串行总线,只需要两根线即可在连接于总线上的器件之间传送信息。IIC总线是一种共享的串行总线,是用于两个设备之间的短距离低速低数据量的数据通信,一般就用在PCB板卡上的设备之间,当然在芯片内部,做SOC设计时也可以把这种协议用在片上功能模块之间。
IIC 通讯协议和通信接口在很多工程中有广泛的应用,如数据采集领域的串行 AD,图像处理领域的摄像头配置,工业控制领域的 X 射线管配置等等。除此之外,由于 I2C 协议占用引脚特别少,硬件实现简单,可扩展型强,现在被广泛地使用在系统内多个集成电路 (IC)间的通讯。
IIC分类:
硬件IIC:一块硬件电路,硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的,硬件(固件)I2C是直接调用内部寄存器进行配置。
软件IIC:软件IIC:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用软件控制管脚状态以模拟I2C通信波形,软件模拟寄存器的工作方式。
1.硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
2.IIC是半双工通信方式
IIC只有两根信号线,一根是双向的数据通信线SDA,一根是有效使能和时钟双功能线SCL,所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。I2C总线上的每个设备都自己一个唯一的地址,来确保不同设备之间访问的准确性。IIC总线上允许连接多个主设备和多个从设备,一般情况下,主设备是单片机或者FPGA,其他都是从设备。
特点:
1)它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个 IIC 通讯总线中,可连接多个 IIC 通讯设备,支持多个通讯主机及多个通讯从机。
2) 一个 IIC 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步,是一种简单、双向、二线制、同步串行总线。
3)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
4)总线通过上拉电阻接到电源。当 IIC 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
5)多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
6)IIC数据有三种传输速率,分别是标准模式(100 kbps)、快速模式(400 kbps)和高速模式(3.4 Mbps),另外一些变种实现了低速模式(10 kbps)和快速+模式(1 Mbps)。
主机和从机的概念:
主机就是负责整个系统的任务协调与分配,从机一般是通过接收主机的指令从而完成某些特定的任务,主机和从机之间通过总线连接,进行数据通讯。发布主要命令的称为主机,接受命令的称为从机。
IIC的高阻态:
漏极开路(Open Drain)即高阻状态,适用于输入/输出,其可独立输入/输出低电平和高阻状态,若需要产生高电平,则需使用外部上拉电阻。
高阻状态:高阻状态是三态门电路的一种状态。逻辑门的输出除有高、低电平两种状态外,还有第三种状态——高阻状态的门电路。电路分析时高阻态可做开路理解。
我们知道IIC的所有设备是接在一根总线上的,那么我们进行通信的时候往往只是几个设备进行通信,那么这时候其余的空闲设备可能会受到总线干扰,或者干扰到总线。为了避免总线信号的混乱,IIC的空闲状态只能有外部上拉, 而此时空闲设备被拉到了高阻态,也就是相当于断路, 整个IIC总线只有开启了的设备才会正常进行通信,而不会干扰到其他设备。
IIC物理层总结:
IIC 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生IIC总线协议所需要的信号进行数据的传递。在总线空闲状态时,SCL和SDA被上拉电阻Rp拉高,使SDA和SCL线都保持高电平。
IIC通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,485也为半双工,SPI和uart通信为全双工。
IIC 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
1)开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
2)结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
3)应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。
IIC 总线时序图:
IIC的通信协议流程:
①表示“总线空闲状态”,在此状态下时钟信号 SCL 和数据信号 SDA 均保持高电平,此时无 IIC 设备工作。
②表示“起始信号”,在 IIC 总线处于“空闲状态”时,SCL 依旧保持高电平时,SDA 出现由高电平转为低电平的下降沿,产生一个起始信号,此时与总线相连的所有 IIC 设备在检测到起始信号后,均跳出空闲状态,等待控制字节的输入。
③表示“数据读/写状态”,在串行时钟线SCL为低电平状态时,SDA允许改变传输的数据位(1 为高电平,0为低电平),在SCL为高电平状态时,SDA要求保持稳定,相当于一个时钟周期传输1bit数据,经过8个时钟周期后,传输了8bit数据,即一个字节。第8个时钟周期末,主机释放SDA以使从机应答,在第9个时钟周期,从机将SDA拉低以应答;如果第9个时钟周期,SCL为 高电平时,SDA未被检测到为低电平,视为非应答,表明此次数据传输失败。需要注意数据以8bit即一个字节为单位串行发出,其最先发送的是字节的最高位。
④表示“停止信号”,完成数据读写后,时钟 SCL 保持高电平,当数据 SDA 产生一个由低电平转为高电平的上升沿时,产生一个停止信号,IIC 总线跳转回“总线空闲状态”。
“数据读/写状态”时序如下图:
在串行时钟线SCL为低电平状态时,SDA允许改变传输的数据位(1 为高电平,0为低电平),在SCL为高电平状态时,SDA要求保持稳定,相当于一个时钟周期传输1bit数据,经过8个时钟周期后,传输了8bit数据,即一个字节。
第8个时钟周期末,主机释放SDA以使从机应答,在第9个时钟周期,从机将SDA拉低以应答;如果第9个时钟周期,SCL为 高电平时,SDA未被检测到为低电平,视为非应答,表明此次数据传输失败。需要注意数据以8bit即一个字节为单位串行发出,其最先发送的是字节的最高位。
IIC器件地址:
每一个IIC器件都有一个器件地址,有的器件地址在出厂时地址就设定好了,用户不可以更改,比如OV7670的地址为0x42。有的器件例如EEPROM,前四个地址已经确定为1010,后三个地址是由硬件链接确定的,所以一IIC总线最多能连8个EEPROM芯片。
IIC地址:
我们知道IIC总线是一个支持多设备的总线,所有设备都共享一根数据线SDA。那么当数据线上传输数据时,每个设备如何才能知道这次传输是传给自己的呢?这就需要每个设备都有一个唯一的地址,每个 I2C 设备都具备7位器件地址。
通常情况下,主机在与从机建立通讯时,主机会将控制命令直接发送到串行数据线 SDA 上,与主机硬件相连的从机设备都会接收到主机发送的控制命令。所有从机设备在接收到 主机发送的控制命令后会与自身器件地址做对比;若两者地址相同,该从机设备会回应一个应答信号告知主机设备,主机设备接收到应答信号后,主从设备建立通讯连接,两者即可开始进行数据通讯。
除了器件地址位,从机设备还有寄存器地址用于寻址寄存器。在数据传输过程中表明寄存器地址,就可以往特定寄存器写入数据。寄存器地址依据从机寄存器数量分为8位、16位。
"如果主机向从机发送地址,从机怎么知道这个地址就是主机的,这个地址是如何计算"
严格讲,主机不是向从机发送地址,而是主机往总线上发送地址(这个地址是某个从机的,而不是主机的,所以不存在“从机怎么知道这个地址就是主机的”的问题),所有的从机都能接收到主机发出的地址,然后每个从机都将主机发出的地址与自己的地址比较,如果匹配上了,这个从机就会向主机发出一个响应信号。主机收到响应信号后,开始向总线上发送数据,与这个从机的通讯就建立起来了。如果主机没有收到响应信号,则表示寻址失败。
主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。
1)如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;
2)如果主机要接收从器件的数据,首先由主器件寻址从器件,然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下,主机负责产生定时时钟和终止数据传送。这也就是主器件对于从器件的两种操作,即写操作和读操作。
(1)数据写操作
单字节数据写操作
Start: IIC开始信号,表示开始传输。
DEVICE_ADDRESS:从设备地址,就是7位从机地址
R/W: W(write)为写,R(read)为读
ACK: 应答信号
WORD_ADDRESS:从机中对应的寄存器地址 比方说访问 OLED中的 某个寄存器
DATA: 发送的数据
STOP: 停止信号。结束IIC标准流程为:
Master发起START
Master发送I2C addr(7bit)和w操作0(1bit),等待ACK
Slave发送ACK
Master发送reg addr(8bit),等待ACK
Slave发送ACK
Master发送data(8bit),即要写入寄存器中的数据,等待ACK
Slave发送ACK
第6步和第7步可以重复多次,即顺序写多个寄存器
Master发起STOP
主机写数据到从机(传输的方向不会改变,即若要改变传输方向必须先发送stop条件)
传输的具体细节:
1.主机控制SDA, 主机首先产生START信号;
2.主机控制SDA,依次设置要寻址的7位从机地址(A6-A0),外加1位数据方向位R/W,0表示主机发送数据(写),1表示主机接收数据(读);
3.从机控制SDA,如果可以回应就发送ACK位(拉低SDA),否则发送NACK(拉高SDA);
4.主机控制SDA, 依次设置从机中的8位寄存器地址(B7-B0),主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,则认为自己正在被主机寻址,根据R/T位将自己确定为发送器和接收器;
5.从机控制SDA, 如果可以回应就发送ACK位(拉低SDA), 否则发送NACK(拉高SDA),这时候主机等待从机的应答信号(A);
6.主机控制SDA,当主机收到应答信号时,发送要访问从机的那个地址, 继续等待从机的应答信号;
7.当主机收到应答信号时,发送N个字节的数据,继续等待从机的N次应答信号;
8.主机控制SDA,产生停止条件,停止发送。
IIC应答信号:
每字节发送完毕都需要有一个应答信号。
Master每发送完8bit数据后等待Slave的ACK。
即在第9个clock,若Slave发ACK,SDA会被拉低。
若没有ACK,SDA会被置高,这会引起Master发生RESTART或STOP流程。
每字节发送完毕都需要有一个应答信号,主机接收到应答信号后,向从机发从停止信号。
单字节写操作中,主机一次向从机中写入单字节数据;页写操作中,主机一次可向从机写入多字节数据(适合大批量数据写入,省时)。
需要注意的是,所有 I2C 设备均支持单字节数据写入操作,但只有部分 I2C 设备支持页写操作; 且支持页写操作的设备,一次页写操作写入的字节数不能超过设备单页包含的存储单元数。
页写过程如下:
(1) 主机产生并发送起始信号到从机,将控制命令写入从机设备,读写控制位设置为低电平,表示对从机进行数据写操作,控制命令的写入高位在前低位在后;
(2) 从机接收到控制指令后,回传应答信号,主机接收到应答信号后开始存储地址的写 入。若为 2 字节地址,顺序执行操作;若为单字节地址跳转到步骤(5);
(3) 先向从机写入高 8 位地址,且高位在前低位在后;
(4) 待接收到从机回传的应答信号,再写入低 8 位地址,且高位在前低位在后,若为 2 字节地址,跳转到步骤(6);
(5) 按高位在前低位在后的顺序写入单字节存储地址;
(6) 地址写入完成,主机接收到从机回传的应答信号后,开始第一个单字节数据的写入;
(7) 数据写入完成,主机接收到应答信号后,开始下一个单字节数据的写入;
(8) 数据写入完成,主机接收到应答信号。若所有数据均写入完成,顺序执行操作 程;若数据尚未完成写入,跳回到步骤(7);
(9) 主机向从机发送停止信号,页写操作完成。
(2)数据读操作
当前地址读操作过程如下:
- 主机向从机发送控制命令,读写控制位设置为高电平,表示对从机进行数据读操作;
- 主机接收到从机回传的应答信号后,开始接收从机传回的单字节数据;
- 数据接收完成后,主机产生一个时钟的高电平无应答信号;
- 主机向从机发送停止信号,单字节读操作完成。
随机读操作:
上图为单字节地址,下图为2字节地址。
主机读取从机中的数据 (传输的方向可以改变,即若要改变传输方向前无需发送stop条件)
标准流程为:
Master发送I2C addr(7bit)和w(写)操作0(1bit),等待ACKSlave发送ACK
Master发送reg addr(8bit),等待ACK
Slave发送ACK
Master发起START
Master发送I2C addr(7bit)和r(读)操作1(1bit),等待ACK
Slave发送ACK
Slave发送data(8bit),即寄存器里的值
Master发送ACK
第7步和第8步可以重复多次,即顺序读多个寄存器
传输的具体细节:
1.主机控制SDA, 主机首先产生START信号;
2.主机控制SDA,依次设置要寻址的7位从机地址(A6-A0),外加1位的R/W(置为0),表明是向从机写命令;
3.从机控制SDA,如果可以回应就发送ACK位(拉低SDA), 否则发送NACK(拉高SDA);
4.主机控制SDA, 当主机收到应答信号时,发送要访问的地址(B7-B0),继续等待从机的应答信号;
5.从机控制SDA, 如果可以回应就发送ACK位(拉低SDA), 否则发送NACK(拉高SDA);
6.当主机收到应答信号后,主机要改变通信模式(主机将由发送变为接收,从机将由接收变为发送)所以主机重新发送一个开始start信号,然后紧跟着发送一个从机地址,注意此时该地址的第8位为1,表明将主机设 置成接收模式开始读取数据,
7. 从机控制SDA, 如果可以回应就发送ACK位(拉低SDA), 否则发送NACK(拉高SDA);
8.从机控制SDA, 发送字节数据,当主机收到应答信号时,就可以接收1个字节的数据,当接收完成后,主机发送非应答信号,表示不在接收数据;
9.主机控制SDA, 如果可以回应就发送ACK位(拉低SDA), 否则发送NACK(拉高SDA);如果要发送STOP条件,必须将最后一个字节的响应设置为NACK(拉高SDA)。
顺序读操作:
与随机读操作相比,读取的数据量要多。 IIC 顺序读操作就是对寄存器或存储单元数据的顺序读取。假如要读取 n 字节连续数 据,只需写入要读取第一个字节数据的存储地址,就可以实现连续 n 字节数据的顺序读取。
顺序读操作过程如下:
(1) 主机产生并发送起始信号到从机,将控制命令写入从机设备,读写控制位设置为低电平,表示对从机进行数据写操作,控制命令的写入高位在前低位在后;
(2) 从机接收到控制指令后,回传应答信号,主机接收到应答信号后开始存储地址的写 入。若为 2 字节地址,顺序执行操作;若为单字节地址跳转到步骤(5);
(3) 先向从机写入高 8 位地址,且高位在前低位在后;
(4) 待接收到从机回传的应答信号,再写入低 8 位地址,且高位在前低位在后,若为 2 字节地址,跳转到步骤(6);
(5) 按高位在前低位在后的顺序写入单字节存储地址;
(6) 地址写入完成,主机接收到从机回传的应答信号后,主机再次向从机发送一个起始信号;
(7) 主机向从机发送控制命令,读写控制位设置为高电平,表示对从机进行数据读操作;
(8) 主机接收到从机回传的应答信号后,开始接收从机传回的第一个单字节数据;
(9) 数据接收完成后,主机产生应答信号回传给从机,从机接收到应答信号开始下一字节数据的传输,若数据接收完成,执行下一操作步骤;若数据接收未完成,在此执行步骤(9);
(10) 主机产生一个时钟的高电平无应答信号;
(11) 主机向从机发送停止信号,顺序读操作完成。