I2C协议详解
I2C协议详解
I2C简介
I2C(Inter-Integrated Circuit),也可以叫IIC、I2C,译作集成电路总线,是两线式串行通信总线,用于设备间的通讯等,标准情况下最高传送速率达100Kbps。顾名思义,I2C通讯只需要两根线,一根是数据线SDA(Serial Data Line),一根是时钟线SCL(Serial Clock Line)。主设备控制时钟线决定I2C的波特率,配合数据线进行数据的传输,这两根线分别通过上拉电阻连接到电源。
IIC(Inter-Integrated Circuit)总线是一种由 NXP(原 PHILIPS)公司开发的两线式串行总线, 用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。
在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。
PS: 这里要注意 IIC 是为了与低速设备通信而发明的,所以 IIC 的传输速率比不上 SPI。
I2C总线物理拓扑图
I2C物理层
I2C硬件层面
I2C有两条总线,一条双向的串行数据线SDA,一条串行时钟线SCL。
SDA(Serial data):串行数据线,用来传送数据;
SCL(Serial clock line):时钟线,用来控制数据发送的时序。
所有接到I2C总线上的设备的SDA线都接到总线的SDA上,各设备的时钟线SCL都接到总线的SCL上。I2C总线上的每一个设备都有一个唯一的地址,以确保不同设备之间的访问互不干扰。
I2C是多主从架构,每个设备都有唯一的地址,一个主设备理论上可以接127个从设备,设备的SDA并接在一起,SCl并接在一起。
I2C总线内部都是采用漏极开路驱动,示意图如图,栅极给电压时mos导通,输出低电平,栅极给0时mos关断输出呈高阻态,那么这里就无法输出高电平。
加上上拉电阻后可以实现高低电平的输出:开关断开时电阻趋于无穷,电流为0,电源电压为输出电压,即输出高电平;开关闭合,输出低电平。只要有一个设备拉低总线电平,总线的电平就会被拉低,这就是线与功能,便于数据的传输和仲裁。
I2C协议特点
-
I2C主设备(master):主要产生时钟,产生起始和结束信号;
-
I2C从设备(slave):可编程的IIC地址检测,停止位检测等;
-
支持不同的通信速率(100KHz~400KHz);
-
SCL和SDA都需要接上拉电阻 (大小由速度和容性负载决定一般在3.3K-10K之间) 保证数据的稳定性,减少干扰;
-
IIC是半双工,而不是全双工,同一时间只可以单向通信。
物理层小结
I2C总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,SCL和SDA被上拉电阻Rp拉高,使SDA和SCL线都保持高电平。
I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,SPI和uart通信为全双工。
I2C协议层
-
开始信号(Start): SCL为高电平时,SDA由高电平向低电平跳变,标志着开始传输数据;
-
结束信号(Stop): SCL为高电平时,SDA由低电平向高电平跳变,标志着结束传输数据;
Start和Stop信号
- 应答信号(ACK/NACK): 所有地址和数据都以8bit为单位传输,如果接受端正确接收了8bit数据,则回复一个bit的“0”信号——ACK信号,如果未正确接收8bit数据,或者接收端不再接受数据,则回复一个bit的“1”信号——NACK信号。即每8bit数据,就会跟1bit ACK/NACK信号。
ACK信号
- 数据有效性: IIC信号在传输过程中,当SCL为高电平(SCL=1)时,数据线SDA必须保持稳定状态,不允许有电平跳变。只有当SCL处于低电平期间,SDA的高、低电平才可以交替变化。也就是说发送数据时,bit数据“0”和“1”的交替是发生在SCL的低电平期间。
I2C bit有效性
数据传输
I2C写数据
数据发送格式:
1、多数从设备的地址为7位或者10位,一般都用七位。八位设备地址=7位从机地址+读/写地址
2、再给地址添加一个方向位位用来表示接下来数据传输的方向:0表示主设备向从设备(write)写数据,1表示主设备向从设备(read)读数据
3、I2C的每一帧数据由9bit组成,如果是发送数据,则包含 8bit数据+1bit ACK;如果是设备地址数据,则8bit包含7bit设备地址 1bit方向
在起始信号后必须传送一个从机的地址(7位) 1~7位为7位接收器件地址,第8位为读写位,用“0”表示主机发送数据(W),“1”表示主机接收数据 (R), 第9位为ACK应答位,紧接着的为第一个数据字节,然后是一位应答位,后面继续第2个数据字节。
写数据
I2C 写(发送)数据格式
字段解析:
- Start:数据传输的开始信号,由主机产生;
- Device address:标识从设备的地址,bit7~bit1;
- R/W:W(write)为主机向从机写数据,R(read)为主机向从机读数据,bit0;
- ACK:主机读数据时,从机做接收,由从机产生ACK信号;
- Word Address:Slave设备内部的数据地址,即主机要往从机的这个地址写数据,上图中Word Address只体现了一个字节,实际上可以有多个字节。如访问8K bytes的 eeprom,就需要2个字节的Word Address来寻址;
- Data:发送的数据,以字节为单位,每8bit数据,从设备回一个ACK信号;
- Stop:数据传输的结束信号,由主机产生。
主机向从机写(发送)数据流程:
-
主机首先产生START信号;
-
然后紧跟着发送一个从机地址,这个地址共有7位,紧接着的第8位是数据方向位(R/W),0表示主机发送数据(写),1表示主机接收数据(读);
-
主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,主机则认为自己正在被主机寻址,根据R/W位将自己确定为发送器和接收器;(注:不要把发送器/接收器同主设备/从设备混淆,当主设备向从设备写数据的时候,主设备做发送器,从设备做接收器;当主设备向从设备读数据的时候,主设备做接收器,从设备做发射器)
-
这时候主机等待从机的应答信号(ACK);
-
当主机收到应答信号时,发送要访问从机的哪个地址, 继续等待从机的应答信号;
-
当主机收到应答信号时,发送N个字节的数据,继续等待从机的N次应答信号;
-
主机产生停止信号,结束传送过程。
I2C读数据
I2C 读(接收)数据格式
字段解析:
- Start: 数据传输的开始信号,由主机产生;
- Device address: 标识从设备的地址,bit7~bit1;
- R/W: W(write)为主机向从机写数据,R(read)为主机向从机读数据,bit0;
- ACK: 正式接收数据后的ACK信号由主机产生。Data传输前的ACK信号由从机产生,因为Data传输前都是主机在给从机“写”数据;
- Word Address: Slave设备内部的数据地址,即主机要往从机的这个地址读数据,上图中Word Address只体现了一个字节,实际上可以有多个字节。如访问8K bytes的 eeprom,就需要2个字节的Word Address来寻址;
- RS: restart信号,表现形式和start信号完全一样。只是在读的过程中,再次触发了一次start信号,所以我们称之为restart;
- Data: 接收的数据,以字节为单位,每8bit数据,主设备(接收器)回一个ACK信号;
- NACK: 当主机读完指定长度的数据时,会在最后一个byte接收完成后,产生一个NACK信号;
- Stop: 数据传输的结束信号,由主机产生。
主机向从机读(接收)数据流程:
主机向从机读数据实际上分了两个步骤,一是把需要希望从从机的哪个地址(Word Address)读数据,通过“写”(W)的方式告诉从机;然后再次发送读(R)信号,这时从机才开始给主机发送信号。
-
主机首先产生START信号;
-
然后紧跟着发送一个从机地址,注意此时该地址的R/W位为0,表明是向从机写命令,通知从机,主机要读的地址;
-
这时候主机等待从机的应答信号(ACK);
-
当主机收到应答信号时,发送要访问的地址,继续等待从机的应答信号;
-
当主机收到应答信号后,主机要改变通信模式(主机将由发送变为接收,从机将由接收变为发送)所以主机重新发送一个开始start信号,然后紧跟着发送一个从机地址,注意此时该地址的R/W位为1,表明将主机设置成接收模式开始读取数据;
-
这时候主机等待从机的应答信号,当主机收到应答信号时,就可以接收n个字节的数据,当接收完成后,主机发送非应答信号(NACK),表示不再接收数据;
-
主机进而产生停止信号,结束传送过程。
数据传输帧格式
I2C数据的传输也遵循一定的格式。它有开始和停止条件,中间进行8bit的数据传输,没有奇偶校验,并且在一个开始条件和停止条件可之间可以传要多少数据有多少数据。提醒一下,我们的总线默认保持高电平。
开始条件:在时钟线保持高电平时,数据线从高电平转为低电平,即检测到一个下降沿,会形成一个开始条件;
停止条件:时钟保持高电平时,数据线从低电平转为高电平形成一个停止条件。
进行数据传输前也就是紧跟开始条件后,我们要传送地址字节,前7位是从设备地址(这也是为什么一个主机理论上最多能接127个从机,2^7-1),第八位是读/写标志位。每8bit传输完成,第九位是应答位。如果是主设备发送数据,就是从设备应答,如果是主设备读取数据,就是主设备应答。
寄存器
控制寄存器控制开始停止条件,每传输完一个字节会进入内部中断,状态寄存器记录单片机的工作状态。作为主机时,分频器寄存器配合内部时钟设置I2C的波特率;地址寄存器是从机地址编址;最后是数据寄存器。
信号分析
通过使用I2C读写eeprom用逻辑分析仪抓信号并分析。
I2C写数据
通过I2C往eeprom的0x0100地址写两个字节的数据,数据为“0x66 0x55”.使用的是16K byte的eeprom,字节的寻址范围为:0~0x3fff,所以word address有两个字节。
I2C读数据信号抓包
下图为eeprom厂家的datasheet里面提供的 “Device address”说明,eeprom厂家规定读写数据区域的地址bit7~ bit4为1010,可配置bit为bit3~bit1,也就是说一个I2C总线上最多可挂8个eeprom。
注:bit7~bit4的特殊约定,只是eeprom厂家做的功能限制,并不是iic协议的限制。
eeprom地址表
我们把图7中的数据包放大来看,如下图:
Device address & R/W字节分析
从上图中可以清楚的看到,SDA的数据信号在SCL的高电平脉冲期间保持稳定,在SCL的低电平脉冲期间进行bit数据“0”和“1”的切换。
I2C读数据
通过I2C从eeprom的0x0100地址读取两个字节。
I2C读数据信号抓包
从上图中,可以看到I2C读过程一共发起了两个start信号,第一个start信号(图中第1个绿色圆点处),SDA上发送了Device address & Write字节以及word address, 第二个start信号(图中第2个绿色圆点处),发送了Device address & Read字节,然后就开始接收数据。
时钟外设读写
写入与读取格式
参照数据手册,时钟外设的写入格式如图所示,需要两个字节后开始写入。
开始条件之后紧跟地址字节,时钟外设的地址是1101 111,读写位是0,得到外设应答后,发送子地址的首地址,我们可以把时钟内部看作有很多片区,我们要在写数据之前把我们要先找到片区区号,再开始写数据,每传完一个字节数据,区号会自动加一,把下一个数据写入下一个片区,直到主设备停止发送。
主设备要读取数据时,开始条件后紧跟地址字节,得到外设应答后,发送要读片区的区号地址,得到外设应答后,发送重复开始信号,再发送外设地址且第8位为读模式,就可以从选定的片区开始读取数据,外设每传送一个字节,区号会自动加一,传送下一个区号的数据,直到主设备不应答后产生停止条件,停止读取。
注意,如果主机不发送不应答信号就发送停止条件,设备容易挂死,可能原因:外设没有释放总线准备继续传输数据给主设备,将SDA拉为低电平,SDA线上的数据只有当SCL为低时才能改变状态;此时SCL释放为高电平等待SDA的变化,互相等待导致挂死(绿色线为SDA,黄色线为SCL):
实测波形分析
下面是写入的波形,两字节后开始写入数据,前两个字节是地址,第一个是时钟外设地址,第二个是我选择在00处开始写入数据。第一个数据0x19写进外设的00,片区,第二个数据0x09写进外设的01片区。
读取的波形,三字节后开始读取数据,第一个是时钟外设地址,第二个是我选择在00处开始读取数据。一个重复开始信号后发送时钟地址和读标志,第一个数据0x19是时钟发送的00片区数据,第二个数据0x09是时钟发送的01片区数据,接收后主机不应答后产生停止条件,停止读取。
I2C示例讲解
以AT24C02为例子
24C02是一个2K Bit的串行EEPROM存储器(掉电不丢失),内部含有256个字节。在24C02里面有一个8字节的页写缓冲器。
A0,A1,A2:硬件地址引脚
WP:写保护引脚,接高电平只读,接地允许读和写
SCL和SDA:IIC总线
可以看出对于不同大小的24Cxx,具有不同的从器件地址。由于24C02为2k容量,也就是说只需要参考图中第一行的内容:
芯片的寻址:
AT24C设备地址为如下,前四位固定为1010,A2~A0为由管脚电平。AT24CXX EEPROM Board模块中默认为接地。A2~A0为000,最后一位表示读写操作。所以AT24Cxx的读地址为0xA1,写地址为0xA0。
也就是说如果是
写24C02的时候,从器件地址为10100000(0xA0);
读24C02的时候,从器件地址为10100001(0xA1)。
片内地址寻址:
芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00~FF,共256个寻址单位。
对应的修改 A2A1A0 三位数据即可
向AT24C02中写数据
操作时序:
MCU先发送一个开始信号(START)启动总线
接着跟上首字节,发送器件写操作地址(DEVICE ADDRESS)+写数据(0xA0)
等待应答信号(ACK)
发送数据的存储地址。24C02一共有256个字节的存储空间,地址从0x00~0xFF,想把数据存储>在哪个位置,此刻写的就是哪个地址。
发送要存储的数据第一字节、第二字节、…注意在写数据的过程中,E2PROM每个字节都会>回应一个“应答位0”,老告诉我们写E2PROM数据成功,如果没有回应答位,说明写入不成功。
发送结束信号(STOP)停止总线
注意:
在写数据的过程中,每成功写入一个字节,E2PROM存储空间的地址就会自动加1,当加到0xFF后,再写一个字节,地址就会溢出又变成0x00。
写数据的时候需要注意,E2PROM是先写到缓冲区,然后再“搬运到”到掉电非易失区。所以这个过程需要一定的时间,AT24C02这个过程是不超过5ms!
所以,当我们在写多个字节时,写入一个字节之后,再写入下一个字节之前,必须延时5ms才可以
从AT24C02中读数据
1、读当前地址的数据
2、读随机地址的数据
MCU先发送一个开始信号(START)启动总线
接着跟上首字节,发送器件写操作地址(DEVICE ADDRESS)+写数据(0xA0)
注意:这里写操作是为了要把所要读的数据的存储地址先写进去,告诉E2PROM要读取哪个地址的数据。
发送要读取内存的地址(WORD ADDRESS),通知E2PROM读取要哪个地址的信息。
重新发送开始信号(START)
发送设备读操作地址(DEVICE ADDRESS)对E2PROM进行读操作 (0xA1)
E2PROM会自动向主机发送数据,主机读取从器件发回的数据,在读一个字节后,MCU会回应一个应答信号(ACK)后,E2PROM会继续传输下一个地址的数据,MCU不断回应应答信号可以不断读取内存的数据
如果不想读了,告诉E2PROM不想要数据了,就发送一个“非应答位NAK(1)”。发送结束信号(STOP)停止总线
3、连续读数据
E2PROM支持连续写操作,操作和单个字节类似,先发送设备写操作地址(DEVICE ADDRESS),然后发送内存起始地址(WORD ADDRESS),MCU会回应一个应答信号(ACK)后,E2PROM会继续传输下一个地址的数据,MCU不断回应应答信号可以不断读取内存的数据。E2PROM的地址指针会自动递增,数据会依次保存在内存中。不应答发送结束信号后终止传输。
软件IIC和硬件IIC
IIC分为软件IIC和硬件IIC
软件IIC:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用软件控制管脚状态以模拟I2C通信波形,软件模拟寄存器的工作方式。
硬件IIC:一块硬件电路,硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的,硬件(固件)I2C是直接调用内部寄存器进行配置。
硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。