it芯片|嵌入式开发中I2C协议是怎么玩儿的?看这篇就够了

it芯片|嵌入式开发中I2C协议是怎么玩儿的?看这篇就够了

文章图片

it芯片|嵌入式开发中I2C协议是怎么玩儿的?看这篇就够了

文章图片

【it芯片|嵌入式开发中I2C协议是怎么玩儿的?看这篇就够了】it芯片|嵌入式开发中I2C协议是怎么玩儿的?看这篇就够了

对于嵌入式开发的朋友来说 , I2C协议实在是再熟悉不过了 , 有太多的器件 , 采用的都是通过I2C来进行相应的设置 。 今天 , 我们就随便聊聊这个I2C协议 。
I2C协议中最重要的一点是I2C地址 。 这个地址有7位和10位两种形式 。 7位能够表示127个地址 , 而在实际使用中基本上不会挂载如此多的设置 , 所以很多设备的地址都采用7位 , 所以本文接下来的说明都是基于此 。 I2C还有一个很重要的概念 , 就是“主—从” 。
对于从设备来说 , 它是啥都不干的 , 更不会自动发送数据;而主设备 , 则是起到控制作用 , 一切都是从它开始 。  除了GND以外 , I2C有两根线 , 分别是SDA和SCL , 所有的设备都是接到这两根线上 。
那么 , 这些设备如何知道数据是发送给它们呢?这就得依靠前面所说到的地址了 。 设备I2C的地址是固定的 , 比如0x50 , 0x60等等 。 因为只能有127个地址 , 地址冲突是很常见的 , 所以一般设备都会有一个地址选择PIN , 比如拉高时候为0x50 , 接地为0x60 。
如果无论拉高还是接地 , 都和别的芯片有冲突 , 那该怎么办呢?答案是:凉拌 , 没办法 。 遇到这种情况 , 只能换芯片了 。
我们来看I2C协议中的数据传输时序图:

SCL是时钟 , SDA承载的是数据 。 当SDA从1变动到0 , 而SCL还是1时 , 表示开始数据传输 。 接下来的7位 , 就是设备的地址 。 紧接着的是读写标志 , 其为1时是读取 , 为0则是写 。
如果I2C总线上存在着和请求的地址相对应的设备 , 则从设备会发送一个ACK信号通知主设备 , 可以发送数据了 。 接到ACK信号后 , 主设备则发送一个8位的数据 。 当传输完毕之后 , SCL保持为1 , SDA从0变换到1时 , 标明传输结束 。
从这个时序图中可以看到 , SCL很重要 , 并且哪个时钟沿是干嘛的 , 都是确定好的 。 比如 , 前面7个必定是地址 , 第8个是读写标志 , 数据传输必须是8位 , 必须接个ACK信号等等 。
前面的时序图并没有标明数据传输的方向 , 我们现在看看写操作的数据流向:

网格的是主设备发送的 , 白色格子是从设备发送的 。 从图示中可以看到 , 对于写操作 , 从设备都只是发送ACK进行确认而已 。  而读操作的数据流向 , 就有所不同 , 如图:


这时候 , 从设备除了发送ACK以外 , 紧跟着的还有数据 。
我们用示波器来查看波形图 , 以便于理解 。
将示波器的X和Y分别接到SDA和SCL , 得到波形并分析如图:


从图中可知时序如下:
由主机发起 , 在SCL为高电平时 , SDA由高到低切变 , 形成开始信号;
接着是7位地址和一位读写标志 , 这里7位地址为0111100 , 即0x3c , 正是我们代码中设置的地址ID;最后一位为0表示写操作;
接着在下一个时钟 , 主机以高电平状态释放SDA , 这时从机响应 , 将SDA拉低了;
接着是两个8位数据00101110与响应 , 即0x2E , 正是“.”号的ASCII码 , 符合预期输出;
还有其它数据和最后的停止位 , 图中被截掉了 。
从图中可知 , 纵向一格是200mV , 则SDA和SCL的电平大概就是350mV;由于信号笔上设置了信号x10 , 因此实际电平应该大概是3.5V(理论上应该是3.3V) 。 横向一格是25us , 10个时钟周期大概用了4格 , 即4x25us=100us , 平均每个时钟周期是10us , 可算出传输频率为1/10us=100000/s , 即100k bps 。