[总系]I2C通信

2019-07-12 19:49发布

I2C总线

SCL:时钟,通常时钟都是由master提供的
SDA:数据

1. 接线

主设备——从设备(两根线都要接上拉电阻)
SDA脚——SDA脚
SCL脚——SCL脚
在这里插入图片描述

2. 协议

  1. I2C设备都有设备地址,可以多对多(多个主设备,多个从设备)
    一对多:这种比较常见(我还没遇到过多对多,手动滑稽),也不会有太多问题
    多对多:需要确保时钟(SCL)同步
  2. SCL时钟速率不要高于从设备

2.1 数据传输步骤如下

  1. 开始条件:SDA为高电平(1),SCL为高电平时(1),SDA由高向低跳变(下降沿)
  2. 发送数据:8个数据位,先传最高位(MSB),然后释放SDA线(1)(拉高电平)
    SCL为低电平时(0),SDA可进行电平转换;
    SCL为高电平时(1),SDA保持不变,接收设备(主设备或从设备)读取数据。
  3. 接收响应:ACK,在第九个周期(可以说是第九个数据位)
    接收设备拉低SDA(0);
    答复发送设备,接收完成;
  4. 结束条件:SDA为低电平(0),SCL为高电平时(1),SDA由低向高跳变(上升沿)
  5. 重复开始条件:master需要在一次通信中进行多次消息交换(例如与不同的slave传输消息,或切换读写操作)
    开始和结束不一一对应,可以发送多次开始条件,然后只有一个结束条件
    a. 主设备发送地址帧(地址+写),发送要读取的寄存器地址(如0xA0)
    b. 主设备发送地址帧(地址+读),接收(0xA0)寄存器数据
    在这里插入图片描述
  6. 时钟拉伸(clock stretching)
    有时候,低速slave可能由于上一个请求还没处理完,尚无法继续接收master的后续请求,即master的数据传输速率超过了slave的处理能力。这种情况下,slave可以进行时钟拉伸来要求master暂停传输数据 —— 通常时钟都是由master提供的,slave只是在SDA上放数据或读数据。
    而时钟拉伸则是slave在master释放SCL后,将SCL主动拉低并保持,此时要求master停止在SCL上产生脉冲以及在SDA上发送数据,直到slave释放SCL(SCL为高电平)。之后,master便可以继续正常的数据传输了。可见时钟拉伸实际上是利用了时钟同步的机制,只是时钟由slave产生。
    如果系统中存在这种低速slave并且slave实现了clock stretching,则master必须实现为能够处理这种情况,实际上大部分slave设备中不包含SCL驱动器的,因此无法拉伸时钟。
    所以更完整的I2C数据传输时序图为:
    在这里插入图片描述

2.2 传输详细内容

  1. 地址帧(address frame):(用于master指明消息发往哪个slave)
    地址帧:7个地址位+1个读写位(0写1读),也支持10bit地址
    地址位:确保芯片Datasheet给的是几位地址位,有的给的7位,有的给的8位(需要左移);直接给地址帧,带读/写
    10bit地址帧:b1111 0XX(W/R)+bXXXX XXXX;
    如下图所示
    在这里插入图片描述
  2. 数据帧(data frames): 由master发往slave的数据(或由slave发往master),每一帧是8-bit的数据
  3. 根据 (1地址帧) 的读写位,确定发送/接收设备
    :和发送地址帧一样,主设备(发送),从设备(接收);
    :反过来,主设备(接收),从设备(发送);
    后续的数据传输中,发送设备发送数据,接收设备需要发送ACK