i2c(或IIC)协议使用两根线进行通信(不包括电源正负极),它们分别为:
1、SDA:数据线,IIC 协议允许在单根数据线上进行双向通信——这条线既可以发送数据,也可以接收数据。
2、SCL:时钟线,注意了,这个时钟线跟我们平时所说的时钟没什么关系,不要以为这根线是用来接手表的。其实,这里所说的“时钟”,更像是我们看音乐会的时候,站在前面最中央处的那个指挥者,或者说节拍器。它的作用就是协调硬件之间的传输节奏,做到步伐一致,不然数据就会乱了。比如,IIC通信里面,当时钟线的电平拉高后,数据线的内容就不能改变,也就是说,SCL高电平时,不能写数据,但可以读。当SCL下降为低电平后,才能向数据线(SDA)写入数据。
IIC 通信以 Start 信号开始,以 Stop 信号结束。
传送开始信号的方法:拉高SCL和SDA的电平,在SCL处于高电平的情况下把SDA的电平拉低。
传送结束信号的方法:拉高SCL的电平,在SCL处于高电平的情况下,把SDA的电平拉高。
这其中,你会发现规律:无论是开始信号还是结束信号,SCL 都处于高电平,前文提过,时钟线拉高就是固定数据线上的内容,显然,在开始和结束信号中,是不能传数据的。在SDA上,开始信号和结束信号刚好相反,Start 时电平拉低,Stop 时电平拉高。下面这张图是从 IIC 的协议手册上盗来的。
写入数据时,主机先把时钟线SCL拉低,然后写入一个二进制位(高电平为1,低电平为0),然后把SCL拉高,此时从机读取这个二进制位。接着第二个二进制位也是这样,主机拉低SCL,写SDA,再拉高SCL,从机读……当发送完 8 个二进制(一个字节)后,在第九个时钟周期,主机把SDA拉高(有时候需要切换为输入模式),再拉高SCL,等待从机写应答;如果主机从SDA上读到低电平,表示从机有应答(你的红包我收到了),要是读到高电平,表示无应答(你啥时候发的红包?我都没看到)。
从机向主机发送数据的过程也一样,SCL仍然由主机操控,SCL拉低后向SDA写数据,SCL拉高后就不能写了,此时主机读SDA上的数据。通常主机在接收完最后一个字节后可以不应答(让SCL和SDA同时高电平),或直接发送 Stop 信号终止通信(毕竟主机权力大,生死予夺都是主机说了算)。
上面的东东看得好像很乱,刚接触时就是这样的,见多了就熟悉了。可以大概地总结一下:
1、SCL低电平时,发送方写SDA;
2、SCL高电平锁定SDA,发送方不能写,接收方读;
3、应答信号:SCL高 + SDA低---> 有应答;SCL高 + SDA高---> 无应答。
其实,我们实际开发中,不了解协议时序也没关系,我们也很少手动去模拟 IIC 通信过程。尤其是像树莓派这种带操作系统的开发板,更不应该手动去模拟,而是直接用现成的库(或者API)。不管你什么语言,你都是先向系统发送指令,然后系统去控制硬件,效率上都无法保证。而且,IIC 协议都是标准化的协议,你每次写程序都去手动模拟通信,浪费时间,意义也不大。这好比我们在 Socket 编程时一样,你不可能总去自己写个协议再来通信吧。一般都会直接用 TCP 或 UDP 协议。
所以,对于IIC协议也是如此,我们了解一下就行了。老周上面在介绍时也是简略化的,所以你可能看得有点晕,若想深入理解,可以看数据手册。毕竟老周不可能把手册上的内容复制过来的,那就是抄袭了。
好,继续。
IIC 总线可以挂多个从机,从机不会主动发起通信,都是由主机发起通信的。因此,主机必须知道要跟哪个从机通信,故挂到总线上的从机必须拥有唯一的地址——这就是所谓的器件地址。就像一个内网中的 N 台电脑一样,每台电脑都要给它分配唯一的 IP 地址,这样你才能知道你正在跟谁说话。哪怕是 UDP 广播,也是有广播地址,192.168.1.255。
IIC 器件地址,7位地址最常见,当然也有 10 位的(老周买的各种模块中都没见到),这个【位】是二进制位,常用的 7 位就是7个二进制位。7 位地址格式如下:
低位在右边,从右到左,我们看到第 1 位是 R/W,表示读写位,就是用来告诉从机,我要读数据还是写数据。“W”头顶上有个横线,表示低电平,即 0 表示写,1 表示读。从第二位到第八位就是从机的地址了。所以,现在你知道为啥地址是7位的原因了吧,就是要留一位来确定读还是写。
假如某品牌的自动铲屎机使用 IIC 通信协议,标签上告诉你它的从机地址是 0x47,先把它弄成二进制。