在2440开发板上,有两个接口SCL和SDA,其中SCL是时钟线,SDA是数据线,他们分别连接一个上拉电阻(控制SDA的电平和SCK电平),这两条线上挂载了许多设备,这些设备也有两条线,分别连接ARM的SCL和SDA。
那么我们怎么传输数据?
比如说和一个存储芯片连接,我们需要把数据发给它,也要从芯片里读取数据。
假设有一个老师和ABCD四个学生,假设老师要发球,那么他会这样做。
- 老师会告诉学生说,注意我要发球了(start)
- 然后老师会申明这个球要发给哪个学生,比如发给A,老师会说,A,我要把球给你了(地址方向,地址A,方向是从老师到A)
- 然后老师把球扔出来(传输)
- 最后A收到球了,他要告诉老师,老师我收到球了(回应)
- 老师确认A收到球后,知道发球的动作完成(P,结束)
那么如果老师要接球,他的流程和发球又会有所不同。
- 类似的,老师首先会告诉学生说,注意啊(start),但是这时候他还没有说要接球还是发球,只是提醒学生自己要开始一次传输了;
- 比如老师要从学生B那里拿球,他会说,B,把球扔给我(地址方向)
- 然后B收到信号,他就把球扔给老师(传输)
- 老师收到球后,回应说,我收到球了(回应)
- 回应收到球后,老师还要再说一句,结束,表示这次动作已经全部完成了(P,结束)
上面的例子中,老师的角色就等同于ARM开发板,各个球员的角色则是挂载在ARM板上的各个设备,他们之间就是通过I2C协议进行交流。
同时,从上面的流程可以看出,每次通信的发起(start)和结束(P),都是老师(ARM板,主设备)主导的,球员(从设备)则是被动配合,这是由于I2C协议是主从结构,支持一主多从,所有的通信都是由主设备发起和结束。
那么,多个从设备下,怎么选择哪个从设备响应主设备的动作呢?
是通过设备地址(1字节)来实现从设备的选择的,每个从设备都有属于自己的地址,这些地址都是写死在芯片里面的,一个主设备最多挂载128个设备,这是因为1字节的设备地址,最高位bit7是用来表示传输方向,实际表示设备地址的只有7位。
通信的数据格式如下,主设备要写时:
- 主设备发出start信号,表示要开始一次传输;
- 主设备发出设备地址和传输方向(写);
- 从设备收到信号后回传主设备,表示可以写了;
- 主设备收到回应后向从设备发送数据;
- 从设备接受完数据后回应主设备,表示收到数据了;
- 循环4-5,将数据发送完毕,最后主设备回传一个结束信号,表示完成本次传输。
类似的,主设备要读时:
- 主设备发出start信号;
- 主设备发出设备地址和传输方向(读);
- 从设备收到信号后回应主设备;
- 从设备传输数据给主设备;
- 主设备接受到信号回应从设备;
- 循环4-5,将数据接受完毕,最后回传一个结束信号给从设备,表示本次通信结束。
注意除了start和P信号,其他信号都要回传,保证数据传输的稳定性。
那么,怎么表示这些信号(start,结束信号)呢?
下图是2410的I2C总线信号传输时序。
可以看出,start信号就是SCL保持高电平,SDA从高变低。停止信号则是SCL保持高电平,SDA从低变高。
怎么传输设备地址呢?
答:逐8位传输,先传MSB。用9个CLK,传8bit数据,第9个CLK是回应。
之后是发数据,发完之后接受回应信号。
从时序可以看出,在SCL低电平时,SDA可变化,在SCL高电平时,SDA需要保持稳定。
还有一个问题,如何在SDA上实现双向传输?
答:使用开极电路,实现。
- 在主设备发送时,从设备不发送,这可以通过SCL控制;
- 主设备发送时,从设备的“发送引脚”不影响数据;
主设备的内部有一个PNP三极管,集电极接出来是SDA,发送脚为A,接三极管的基极,从设备也有一个PNP三极管,同样是集电极接SDA,发送脚为B,接三级管的基极。
那么就可以列一个真值表出来:
A | B | SDA |
---|---|---|
0 | 0 | 1(由上拉电阻决定) |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 0 |
当A或者B为高电平时,三极管导通,SDA就会被拉低,两个都不导通时,SDA由上拉电阻决定,输出1。
- 不想影响SDA时,不驱动三极管;
- 想输出高电平,不驱动三极管;
- 想输出低电平,驱动三极管。
那么数据的传输就是这样的,比如主设备要发送8bit数据给从设备。
- 前8个CLK,从设备不驱动三极管,数据由主设备决定,传1就不驱动,传0就驱动;
- 第9个CLK,由从设备决定数据,主设备不驱动三极管,由从设备决定,决定发送ACK或NACK。
主设备不驱动三极管,那么如果从设备不驱动三级管,SDA就会是高电平,否则就是低电平。当从设备回传ACK时,从设备会有一个动作,也就是驱动三极管,也就是说ACK为低电平,No ACK为高电平。
另外,I2C协议只规定了如何传输数据,数据的含义则是由设备决定。
课后作业:
阅读AT24Cxx芯片手册,了解其他读写方法。
下图是AT24Cxx芯片手册中,当前地址的读时序。
- 首先还是发送一个start信号;
- 然后是7bit的设备地址,先传MSB,然后是1bie的读信号;
- 接收ACK信号;
- 读取数据;
- 注意当主设备读取完需要的数据后,需要回传一个No ACK信号加一个STOP信号,表示数据读取完毕,而不是回传ACK信号。
下图是随机读取的时序。
- 首先,还是一个START信号;
- 然后是7bit的地址信号(MSB)+1bit的写信号,注意这里是写信号不是读信号了;
- 接收到ACK信号;
- 写入一个地址数据地址;
- 接受ACK;
- 再发送一个START信号,之后的就是一般的读取流程了。
随机读取和正常读取相比,就是多了一个dummy write的操作,这个操作设置了要读取数据的地址,设置完成后就可以像普通读取那样一次读取数据了。
其中的(* = DON’T CARE bit for 1K)表示数据量不要超过100bit,具体含义待后续课程学习完毕后研究。