i2c协议注意几点就很好的使用它:
1)由一个主设备,一个或多个从设备组成,所有的信号发起都是由主设备发起,从设备根据这些信号做一些应答。
2)i2c发送时序是先发高位再发低位。
3) 本文以发8位信号为例, 主设备会先发一个7位地址,和一位读写位,从设备匹配自己的地址,如果匹配上,就做应答,否则不做操作
4)开始位:主设备发起,clk为高电平时,sda从高到低; 从设备发现这样一组信号,就认为主设备要开始操作自己了,做好接收的准备工作。
5) 从设备收数据:主设备发送了开始位后,把clk拉低,只有clk拉低,sda才可以做高低变化; 当clk被拉高时,从设备就会去读取sda的高低电平值;clk再次被拉低时,从设备认为此位已读取完毕,认为是有效位,等待clk再次拉高,读取下一位。
6)校验位:主设备发送完8位后,第9位是校验位, 读取到低电平为有效;主设备把clk拉低,sda io换成输入模式(上拉电阻,默认高电平)读取第9位,clk再次拉高,读取从设备发来的校验位。
分两种情况:
1.写操作:主设备把clk拉高,等待读取校验位,从设备发现clk拉高后,就把sda拉低,告诉主设备,成功接收前8位数据。
2.读操作:主设备发送IC地址和寄存器地址,这两个字节的校验位都是由从设备来拉低; 从设备开始向从设备发送数据,clk为低时,sda变化,主设备clk拉高时读取sda, 校验位由主设备拉低; 当从设备发送完最后一个字节后,主设备强制把校验位拉高,告诉从设备不要需要再发了, 从设备发现这个校验位没有被拉低,认为主设备接收错误,也就结束发送了,当然了,从设备自己知道是最后一个字节。
7)结束位:主设备发起,clk为高电平时,sda从低到高。
另外:linux 设置IO方向操作瞬间时, 设置输入时:IO电平默认为高; 设置输出时:IO电平默认为低。
通道1为sda, 通道2为clk
主设备发送0x00(写操作)
这个是模拟IO的波形时序,前两个下去又上去的波形为linux 设置IO为输出时,为低电平,后又初始化为高电平。clk一直为高时,sda拉低又拉高,其实已经产生了开始位和结束位,开始后马上又结束了,之后clk拉低又拉高,从设备不做事情,因为已经结束了。后面的波形才是从设备可以识别的,数据在开始位和结束位之间。
通道1为sda, 通道2为clk
主设备发送0xC8地址,(读操作)
实际数据为0xC9 0x04 0x11 0x33 0x43
发送地址0xC8, 读取0x04 0x11 0x33 0x43
这个是标准I2C的波形时序
上图图解:
1,2,3,4,5都 是校验位。5号是被主设备主动拉高,告诉从设备要结束了,因为读完最后一个字节。
C为开始位
D 为停止位
A 为读写位
B :我们重点说说B, 为什么会sda在clk为低时时被拉高,是因为主设备读完0x04这个字节后,由从设备去拉高校验位,主设备拉低校验位,告诉从设备已成功读取。其实读完其它0x11,0x33,0x43校验位也会被从设备拉高,只不过是由于这三个字节的第0位是1,所以看起来没有被拉高。
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-10/147673.htm