很久以前就听说总线这个词了,一直不懂,所以觉得很牛叉。。。这次有机会学习,就干脆一起看看吧。
1 环境介绍
说实话,计算机的学习最好还是有个环境,裸学真的要难一些。这次搭的环境总的来说还是用之前的树莓派Pico搭配那个祖国版的saleae逻辑分析仪。设备用的是一个I2C驱动的OLED的屏。
逻辑分析仪的使用可以看这篇:逻辑分析仪小试-CSDN博客
电路的基本原理可以参考这篇:显示学习1(基于树莓派Pico) -- 基础_树莓派pico ssd1315-CSDN博客
因为确实没啥硬件经验,在中间遇到了两个坑。
第一个是抓信号的线应该怎么接。如果是软件,这个直接wireshark,或者命令啥的。处理硬件时候顿时傻眼了,本来我以为是串联,先接到逻辑分析仪in,逻辑分析仪一个out再出去。结果找半天都没看到这功能。后面找了半天,原来直接并联就可以了。
第二个问题是接上去之后,I2C上有信号,但是数据异常了。也是一头懵。查了半天,后面看到有GND,有个视频也说要接地。所以多插了一个GND口。好了,虽然偶尔还有点问题(并联的口不能挨着,不知道原因),但是基本能用了。
接法如下:
2 I2C信号
用了逻辑分析仪,信号就很直白了。开始的是这样的。
回头看看代码:
第一行是这个。这个是或操作,对结果没影响,所以还是0xAE。
发送的代码是:
self.addr = 0x3cdef write_cmd(self, cmd):self.temp[0] = 0x80 # Co=1, D/C#=0self.temp[1] = cmdself.i2c.writeto(self.addr, self.temp)
命令是:
SET_DISP = const(0xAE)
SET_DISP | 0x00, # off
对应的波形就是,可以看到,第一段就是地址0x3c,第二段固定是0x80,第三段就是命令0xAE。每一段都有一个ACK,这是就是屏幕发的。
为什么地址是0x3C。查了一下资料,SSD1315的默认I2C地址通常是0x3C或0x3D。这里说一下地址这个词,真的很容易迷惑人,和我们一般理解的地址毛关系没有,其实就是一个设备ID。。。
那0x80又是什么鬼?只有去手册或者资料。这个是SSD1315/SSD1306的通信规定(不是所有的I2C设备)。这里有两个,0x80和0x40。如果是0x80,表明后面传输的是命令。如果是0x40,表明后面传输的是数据。
最后是一个0xAE,这个是代码里面的。就不用多说了。
再看后面的代码
SET_MEM_ADDR,
SET_MEM_ADDR = const(0x20)
对应的波形是和上面一样,第一段是地址0x3c,第二段固定是0x80表示命令,最后那段就是实际命令0x20。每段也有一个屏幕设备发的ACK。
3 协议解析
有了这个实验,再看看I2C协议。
I2C有两根线。
SDA(Serial Data Line):串行数据线,用于传输数据。
SCL(Serial Clock Line):串行时钟线,用于同步数据传输。每一个时钟周期大概是5.375us。
对应图中,上面的就是SDA,下面的就是SCL。
I2C信号的开始:
SDA拉低,SCL维持高位。
跟着就是数据包:
一个包是9个bit,前面8个是发送者发出,最后会再附加一个bit是接收者发ACK,表示设备收到,将SDA拉低。可以看到,上面的包最后一个都是低位。
怎么看数据是0还是1呢?查了一下资料,说是SCL上升中,看SDA的电平,如果是高就是1,如果是低就是0。那么翻译一下上面的图。
就是0111 1000 0,一共9个bit位。前面7个是0111 100。正好就是0x3C。第8个是读写位,1为写读作,0为写操作。这里的就是写。最后的第9位就是ACK,0表示响应了,1就是没响应。这里也是响应了。
从协议来看,地址有7个bit,也就是十进制的127。看来正常状态下一个I2C总线可以挂127个设备。感觉正常也是够了,不过挂多了可能影响速度,而且可能设备地址会冲突。
最后是结束包。
主设备在 SCL 保持高电平的情况下,将 SDA 线从低电平拉高。
一段完整的波形如下:
4 小结
这里只是简单介绍一下,其实I2C还有很多一些细节,比如冲突解决,协商之类的,这次就不写了。
从上面分析终于可以明白什么是总线。本质就是一根线传信息(真的就是总的来说一根或几根线)。假如说有两个人,都拉着一根线,这根线只能上下摆动,不能说话或者别的,只能通过这根线传递信息。总线协议,就是约定大家怎么甩绳子而已,本质上就是这么回事。
比如说,绳子默认都是放下面。A要说话了,就把绳子往上甩一下。B就知道A要说话了,然后约定个时间1秒间隔,往上甩就是1,不甩就是0。一次甩8下。B收到了就往上甩一下,没收到就不甩。好吧,总线,或者说I2C总线基本上就是这么回事。
从上面的分析看看,I2C协议还是相对简陋,基本上就是物理层的东西,很多实际内容都要设备定义,比如上面的0x80和0x40。至于为什么用两根线,说是为了确保数据传输的同步性和可靠性,尤其是在多主多从的复杂总线系统中。没详细研究了。
那么像上面说的只用一根线的有吗?还真有,如下:
FPGA - 单总线协议(one-wire)_单总线通信协议-CSDN博客