I2C:同步串行2线方式进行通信(一条时钟线SCL,一条数据线SDA)
是一种串行总线
I2C 总线的主要特点是接口方式简单,两条线可以挂多个参与通信的器件,即多机模式,而且任何一个器件都可以作为主机,当然同一时刻只能有一个主机。
有接入的器件保持高电平,这条线才是高电平,而任何一个器件输出一个低电平,那这条线就会保持低电平,因此可以做到任何一个器件都可以拉低电平,也就是任何一个器件都可以作为主机
虽然说任何一个设备都可以作为主机,但绝大多数情况下我们都是用单片机来做主机,而总线上挂的多个器件,每一个都像电话机一样有自己唯一的地址,
I2C总线是通过上拉电阻接正电源。当总线空闲的时候,两根线均为高电平。
I2C总线传输协议:
数据位有效性规定SCL为高电平期间,数据线上的数据必须保持稳定,只有SCL为低电平期间SDA状态才允许变化。
I2C 通信有起始信号、数据传输和停止信号,
起始信号:
SCL为高电平期间,SDA有高变低
终止信号:
SCL为高电平期间,SDA由低变高
个人理解:当起始信号产生的时候,SDA由高变为低,占用了总线 。
当终止信号产生的时候,SDA由低变高,总线恢复自由。
起始终止信号均由主机发送
数据传输部分,可以一次通信过程传输很多个字节,字节数是不受限制的,而每个字节的数据最后也跟了一位,这一位叫做应答位,通常用 ACK 表示,有点类似于 UART的停止位。
I2C 每次通信,不管是发送还是接收,必须 2条线都参与工作才能完成,
I2C 通信是高位在前,低位在后
SCL 在高电平的时候,SDA 绝对不可以变化,因为这个时候,接收方要来读取当前 SDA 的电平信号是 0 还是 1,因此要保证 SDA 的稳定,
应答位的作用:
当主机发送数据,没法送一个字节,都需要读取从机应答位,当从机空闲,发送应答0,当从机处理其他工作,发出非应答1,主机则发送终止信号结束继续传送。
主机通过从机的应答位来判断从机是否成功接收数据。
当主机接收数据时,他收到最后一个字节后,必须向从机发送一个传送结束的信号。这个信号由对从机的非应答实现。然后从机释放SDA线,允许主机产生终止。
I2C 通信的起始信号(Start)后,首先要发送一个从机的地址,这个地址一共有 7位,紧跟着的第 8 位是数据方向位(R/W),“0”表示接下来要发送数据(写),‘“1”表示接下来是请求数据(读)。
当我们发送完了这 7 位地址和 1 位方向后,如果发送的这个地址确实存在,那么这个地址的器件应该回应一个 ACK(拉低 SDA 即输出“0”),如果不存在,就没“人”回应 ACK(SDA将保持高电平即“1”)。
响应ACK(Acknowledge)和非响应NACK(Not Acknowledge)
每个字节传输必须带响应位,相关的响应时钟也由主机产生,在响应的时钟脉冲期间(第9个时钟周期),发送端释放SDA线,接收端把SDA拉低。以上图传输101010101为例,SCL第9位时钟高电平信号期间,SDA拉低其代表了有ACK响应位。
当在SCL第9位时钟高电平信号期间,SDA仍然保持高电平,这种情况定义为NACK非响应位。这种情况下,主机可以直接产生STOP条件终止以后的传输或者继续重新START开始一个新的传输。以下情况会导致出现NACK位:
利用库函数_nop_()可以进行精确延时,一个_nop_()的时间就是一个机器周期,这个库函数包含在 intrins.h 这个文件中,‘’
数据传送过程:
S一个起始信号,有阴影的是主机发的数据,没阴影的事从机发的数据,主机首先发送一个起始信号,(时钟为高的时候,数据从高变低就会产生一个起始信号。)。A表示应答。完了要把从机的地址发送过去,为0的话就是说主机要发数据了,从机收到数据后会回复一个应答A,主机收到一个就可以把数据给他了,从机收到一个数据有一个应答,主机又发送数据,当发到最后一次数据,就是说当发到这个数据以后不希望继续发送数据以后,从机不管应答还是非应答,主机要结束这次传输的话只需要发一个停止信号P就可以了。就结束了整个数据传输。
从从机上面读数据:首先也是主机发一个起始信号,然后是7位从机的地址,最后一位为1表示读,收到这个之后来从机回复一个应答,然后从机往主机发数据了,主机收到以后也要给一个应答,完了以后从机又发送数据,当主机不希望继续接受的时候主机要发送一个非应答,然后一个停止信号。就结束了本次读数据,
当发送方向需要改变的时候怎么发送,首先有主机发送一个起始信号, 然后7位从机地址,0是发送,从机收到以后一个应答,然后主机开始传送数据,传完一个之后不需要再传了,这时候不管是应答还是非应答都不管了直接再发一个起始信号, 然后从机地址,把读写方向为改为1读,然后从机收到应答,发送数据,然后主机收到不希望继续发送一个绯应答,然后停止信号,结束本次传输。
前七位是地址,最后一位是读写方向位。
前四位固定,后面三位是可编程的。2的3次方,接八个器件
用信号模拟IIC
起始信号,时钟线为高电平期间,这个数据线有高变低,数据线为高要大于4.7us拉低时间也要大于4us。
起始信号产生完了之后,SDA被我们单片机拉低了,我们应该释放一下让SDA=1;
终止信号:时钟信号在高电平期间,这个数据线由低变高,产生终止信号,低电平期间要大于4个us,高电平期间要大于4.7个us。
应答信号:时钟线在高电平的时候要大于4us,数据线是低电平
非应答信号:时钟线在高电平的时候要大于4us,数据线是高电平
起始信号:SCL=1高电平然后SDA=1高电平,SDA延迟5us,然后SDA拉低5us,这样产生一个起始信号
SCL=1 SDA =1,再等于0由高变低
终止信号:SCL = 0,SCL低电平才允许SDA有效变化,SDA=0,SCL=1,延时5us,SDA=1延时5us
SCL=1 SDA = 0 再等于1 由低变高
发送数据:想要SDA发生变化,必须时钟线号为低的情况下才可以。
起始信号:终止信号:
读有一个返回值的。
主机读应答: 主机发送应答无返回值:
可以进行通信了,发数据的函数:
宏定义