I2C

参考:
https://www.cnblogs.com/aaronLinux/p/6218658.html
https://blog.csdn.net/sternlycore/article/details/85600668
https://blog.csdn.net/CSDN4646/article/details/82756282

起始条件&停止条件

起始条件:SCL线是高电平时,SDA线从高电平向低电平切换
停止条件:SCL线是高电平时,SDA线从低电平向高电平切换
重复起始条件:和起始条件相似,重复起始条件发生在停止条件之前。主机想继续给从机发送消息时,一个字节传输完成后可以发送重复起始条件,而不是产生停止条件

start是在scl是高电平的时候sda的一个下降沿来表示一个i2c的开始信号,到了i2c传输的内部,scl是低电平的时候,所有数据都是无效的,也就是说,硬件上start只是操作sda,令sda产生下降沿。
restart是在一个i2c的时间段内实现在scl高电平的时候的一个sda的下降沿呢,因此,要实现,所操作的是先令sda成高电平,在令scl来个高电平,再令sda成低电平,其实质就是操作一个scl的高电平内产生一个sda的下降沿

I2C_第1张图片

协议代码
I2C_第2张图片

字节格式

  1. SDA数据线上的每个字节必须是8位,每次传输的字节数量没有限制。
  2. 每个字节后必须跟一个响应位(ACK)。
  3. 首先传输的数据是最高位(MSB)
  4. SDA上的数据必须在SCL高电平周期时保持稳定,数据的高低电平翻转变化发生在SCL低电平时期

I2C_第3张图片

发送一个字节 即把bit值转化成高低电平
I2C_第4张图片

读取一个字节
I2C_第5张图片

响应ACK(Acknowledge)和非响应NACK(Not Acknowledge)

每个字节传输必须带响应位,相关的响应时钟也由主机产生,在响应的时钟脉冲期间(第9个时钟周期),发送端释放SDA线,接收端把SDA拉低。以上图传输101010101为例,SCL第9位时钟高电平信号期间,SDA拉低其代表了有ACK响应位
当在SCL第9位时钟高电平信号期间,SDA仍然保持高电平,这种情况定义为NACK非响应位。这种情况下,主机可以直接产生STOP条件终止以后的传输或者继续重新START开始一个新的传输
I2C_第6张图片协议代码
I2C_第7张图片

I2C_第8张图片

7-bit 地址格式和读写位

一个7-bit的地址是从最高位(MSB)开始发送的,这个地址后面会紧跟1-bit(R/W)的操作符,1表示读操作,0表示写操作。 接下来的1 bit是NACK/ACK,当这个帧中前面8 bit发送完后,接收端的设备获得SDA控制权,此时接收设备应该在第9个时钟脉冲之前回复一个ACK(将SDA拉低)以表示接收正常,如果接收设备没有将SDA拉低,则说明接收设备可能没有收到数据(如寻址的设备不存在或设备忙)或无法解析收到的消息,如果是这样,则由master来决定如何处理(stop或repeated start condition)
I2C_第9张图片

7-bit寻址数据传输

I2C_第10张图片
I2C_第11张图片

I2C通信时序图解析

写数据

I2C_第12张图片主机写一个字节代码
I2C_第13张图片

读数据

I2C_第14张图片

I2C_第15张图片

数据写操作I2C_第16张图片

数据读操作

I2C_第17张图片

附加

数据有效性

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
但是,虽然只要求在高电平期间保持稳定,但要有一个提前量,就是数据在SCL的上升沿到来前就准备好,因为数据是在SCL的上升沿打入到器件EEPROM中的。
I2C_第18张图片

数据的传送

在I2C总线上传送的每一位数据都有一个时钟脉冲对应,即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据的传送是 边沿触发

工作过程

总线上所有通信都是由主控器引发的。
主设备向从设备发送数据:
主设备寻址到从设备后,发送它所要读取或写入的从设备的内部寄存器地址(该寄存器地址由自己设定,用于存放写入或读取数据的存放位置);之后,发送数据。数据发送完毕后,发送停止位。
EEPROM收到停止信号后,进入到一个内部的写入周期,大概需要10ms,期间任何操作都不会被EEPROM响应(以这种方式的两次写入之间要插入一个延时,否则会导致失败)。

I2C_第19张图片

你可能感兴趣的:(协议)