暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

理解I²C总线

术道经纬 2019-07-28
465

I²C(Inter-Integrated Circuit)总线是一种同步的,双向通信的串行总线,诞生于1982年,当时支持的通信速率只有100kbit/s,1992年引入Fast-mode,速率达到400 kbit/s,1998年引入High-speed mode,速率更是达到3.4 Mbit/s。

I²C由2条线构成,一条数据线,一条时钟线,分别用SDA(Serial Data Line)和SCL(Serial Clock Line)表示。这2条线都是开漏输出(open-drain),外接上拉电阻(pull-upresistor),因此在不通信(释放总线)的状态下都是高电平(power rail)。

I²C协议中,产生时钟信号并发起数据通信的设备被称为master,接受时钟信号并响应master寻址的设备则被称为slave。I²C支持multi-master和multi-slave,在multi-master环境中,当一个master将总线的电平拉低后,另一个试图拉高总线的master将会halt,以避免出现将总线同时拉高和拉低的局面,造成短路。

I²C通信由master产生START信号发起,这个START信号是通过保持SCL为高电平,将SDA由高电平变为低电平(拉低)实现。通信的结束靠的是保持SCL为高电平,将SDA由低电平变为低电平(释放)的STOP信号。

SCL的每一个时钟脉冲可传输SDA上的一个bit,当SCL为高电平的时候,SDA上代表bit的电平必须保持稳定,以保证采样的正确。当一个8bit的字节通过SDA传输时,首先传送的是MSB(Most Significant Bit)。发送方在发完一个字节的数据后,会暂时让出SDA的控制权,目的是让接收方能够通过将SDA置低的方式发送ACK bit,以表明这个字节的数据已被正确接受,这样发送方才可以继续发送接下来的字节。

反之,在字节发送完后的下一个SCL时钟,如果SDA依然为高电平,就是NACK,说明数据没有被正确接收,或者是作为接收的一方,不想再接收了。

写寄存器

I²C的每一个slave设备会有一个7 bits的地址(极少情况下是10bits),内部有若干的寄存器(对于EEPROM来说则是存储单元),来看下master往slave的一个寄存器写数据的过程是怎样的:

首先,当然是一个START信号,之后master会往总线发送要访问的slave的地址(相当于广播),紧跟着7 bits地址后的,是读写标志位,1代表read,0代表write。总线上的slave会检查这个地址是否就是自己的设备地址,如果是的话,就给予ACK应答,并准备接收接下来的数据了,如果不是的话,自然会忽略之后总线上传输的数据。

接下来master会发送它想要访问的slave中的寄存器地址,然后是发送想要写入这个寄存器的数据。slave正确接收这个寄存器数据后,会自动将当前寄存器的地址加1,master之后再发送的数据就会写入后续地址的寄存器中,直到master主动发送STOP信号结束这次通信。

读寄存器

读slave寄存器数据的过程要稍微麻烦一些,前面的过程跟写寄存器都是一样的,分化出现在master发送完寄存器地址后。这时,master会再次发送START信号,然后再次发送slave器件的地址,不过此时读写标志位的值就是1了。既然是要读slave寄存器数据,只能是由slave自己将数据发送到总线上,所以得把SDA的控制权交给slave。

slave发送完指定寄存器的数据后,也会将当前寄存器的地址加1后移,如果master回的是ACK呢,slave就接着传送下一个寄存器里的数据,如果master回了NACK,说明它不想再读接下来的寄存器了,那slave也就停止发送了,最后,还是mater发STOP信号收尾。

为什么不是在第一次发送slave器件地址的时候,就将R/W位置为1呢,像这样:

这种啊,是用于master读取slave中当前寄存器的地址的(你可以理解为一个指针吧),而不是读取寄存器里的数据的。


文章转载自术道经纬,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论