首先说一下串口通讯,只能在两个设备之间进行,如下图:
若三个设备相互通讯,则每个设备需要两组串口。它们其实是三组相互独立的串口通讯。如下图:
若是四个设备相互通讯就更麻烦了,以此类推。这样一来,最突出的问题是线路连接复杂。
为了解决上述痛点,大佬们设计了一种总线通讯,总线通讯有很多种协议,如:
这里主要介绍IIC(常读作I方C) 通讯,全称Inter-Integrated Circuit,意思是芯片与芯片之间的通讯。
可以看到,使用I2C通讯之后,即使有很多芯片,线路连接显得也十分简单。
I2C通讯一般采用一主多从模式,例如我们的单片机是主机,而其他设备都是从机,那他是如何实现通讯的呢?
以单片机向从属设备写信息为例,可以看到,这里是一帧标准的写数据帧,如下图。
串口通讯的两根线分别是发送和接收,
而I2C这两根线分别是时钟线和数据线,如下图。则上面的一帧写数据是由时钟线和数据线共同作用的,即在在同一时间,要么在发送信息,要么在读取信息。
当处于空闲状态时,数据线和时钟线都处于高电平状态.
而当开始传递信息时,比如传递第一位起始位,此时必须要在时钟信号为高电平期间,数据信号完成由高到低的跳变,也就是下降沿,这样起始信号就发送完成了。
而以下是7位设备的地址码,因为有很多从属设备,每一个从属设备的地址码都是唯一的。
为了要区别和哪一个从属设备通讯,需要先发送7位地址码,7位不同的0或者1的排列组合,一共可以表示128种结果。
它的“0”或“1”可这样表示:
当时钟线位高电平时,数据线上的数据必须保持稳定。比如时钟线为高时,数据线上的数据始终为高,如此一来就完成了逻辑“1”的传输。
若数据线上始终为低电平,则表示逻辑“0”.
若发送一组数据:
也就是要和地址为1010 000的设备通讯。
假设24C02的地址就是1010 000,如下图:
此时就是这个单片机和这个24C02进行通讯
接下来的一位是读写数据位。
如果想要写数据,就给其置0,读数据是置1。再往下一位是应答信号,这个信号是从机发送给主机的。
若从机收到了之前的信息,它会回复“0”,没有收到或者(主机)读取接收完成回复“1”.
下面八位是设备寄存器的地址:
这需要给24C02通讯,如下:
24C02是一个存储器,其可以存储256个字节
而我们发送的8位寄存器地址正好可以访问这256个字节,例如我们写的寄存器地址是0x01
(而0x01的二进制是0000 0001),就会往上图的0x01写入数据。然后单片机需要存储器返回一个应答信号(此时为0),告诉主机写入成功。最后再写入停止位。
停止位与起始位相反,是当时钟信号为高时,数据信号需要由低到高的跳变。
这样一个标准的写数据帧就完成了。
那如何读取数据呢?跟写数据其实差不多,以下是一个标准的读数据帧,也是首先写入设备地址,然后写数据。接下来写的是寄存器的地址,在收到从机的应答信号之后,主机需要再发送一个起始信号,然后需要再发送一遍设备的地址,然后才能发送读数据。之后存储器就会把寄存器里面的数据发送给单片机,这样就完成了一帧数据的读取(最后的应答信号为1,是由主机发给从机)。