实际上,I2C 是同步的串行通信总线,一般用于控制信号,比如控制 LCD, Camera等设备。另外,大部分传感器有 I2C 的接口。I2C 是依靠时钟信号来传递数据的。所以有主设备(产生时钟的信号)和从设备(接收时钟的信号)之分。I2C 的通信每一次操作都是由主设备的发起的。
既然 I2C 是依靠时钟传递的信号,那么在连线上就有时钟钱 (SCL) 和数据线 (SDA),然后为了电势与大地相同,自然少不了地线 (GND)。为了方便没有接触过 I2C 总线的同学们理解这三个名词,贴上名词的全称:
Shared clock signal (SCL)
Shared data line (SDA)
Common ground reference (GND)
单看上面的图,为啥有三个 I2C 设备连接在一起呢?这三者之间又是什么关系?
其中,写有 Master Device 的 I2C 设备,称为主设备,另外两个为从设备。从主设备引出的 SDA 和 SCL 线,构成 I2C 的总线。一个 I2C 的主设备可以提供一条 I2C 的总线。一条总线上,最后可以连接 127 个 I2C 的从设备。
等等,为啥是 127 个呢?主要是 I2C 的地址有 7 位和 10 位两种地址。也就意味着,对于 7 位的地址表达的数据最大可以到 2^7=128,减去一个主设备,就是 127 个从设备了。这里的 I2C 设备地址,就是上图的 Address: 0x3c 和 0x4c,I2C 的主设备是通过从设备的地址,来找到从设备的。请注意,I2C 的主设备,是没有设备地址这一说法的。
我们还需要了解 I2C 的一些硬件信息:
I2C 是半双工,可以有主 -> 从方向的数据,也可以有从 -> 主方向的数据,但是同一时刻,只能有一种传输方式。这点和 SPI 是有差别的,SPI 总线支持全双工模式。但它同时只能访问一个从设备,由片选信号 (CS) 来决定。这就很明显了,I2C 通常用于控制命令的传输。而 SPI 通常用数据的批量传输。
了解完 I2C 的基本硬件信息。我们来了解一下 I2C 的从设备操作方式。不多不多,就是三大步。
连接从设备
对从设备进行读操作
对从设备进行写操作
设备连接
先要检查我们的物联网设备上有没有 I2C 总线。这时需要补充一下,有可能你的开发板上有多个 I2C 的总线。这时候, I2C 的总线地址 (此处非 I2C 的设备地址) 是有多个的,要明确你的 I2C 设备是接在哪个 I2C 的总线上。这也可以理解,为什么得到的 I2C 总线的数据是用 List 类型进行存放的。
如果有总线,我们再查找当前的 I2C 总线上对应的 I2C 设备。
关键的接口是 manager.openI2CDeivce(..),这个函数有两个参数,DEVICE_NAME 是用户定义的一个字符串,表示设备的名称。I2C_ADDRESS,也是之前所说的 I2C 从设备上的地址,这个地址在当前的 I2C 总线上是唯一的。
读写操作
首先得把 I2C 的操作流程搬出来说了。
这张图翻译成中文就是这样子的:
这样就完成了向设备地址为 0x30 的 I2C 的设备,寄存器地址为 0x10 的设备上读或者写入 0x06 这个数据。
那怎么知道往从设备是读数据,还是写数据呢?实际上 I2C 是 7 位的地址位。但是一个字节是 8 位,那位,其中有一位叫做读写位。如果那一位设为读,就是去做操作,如果设为写,就是写操作。实际上,在示波器上我们还能看到另外的一个 ACK 位,保证硬件上传输正常。
那么,加上 I2C 的读写位之后, I2C 数据传输会是什么样的呢?
我们可以看到, I2C 数据传输的时序,从硬件上来说 SCL 是按周期发的时钟信号,当 SCL 是高电平时,SDA 产生一个下降沿,这时候开始数据传输。其中传输 I2C 的从设备地址共有 8 位,1-7 位是地址,第 8 位是读写位,0 表示写,1 表示读。然后硬件自动产生 ACK 位。接下来就是数据传输的整个过程,最后当数据传完后,SCL 为高电平,SDA 产生上升沿时,产生 STOP 操作。实示上,在 I2C 做读操作需要往 I2C 的设备写入随机值,再去读,不过这些操作在 I2C 相关的接口中已经为我们封装好了。
这么大篇幅介绍了 I2C 的原理,还有 I2C 的时序,操作流程。实际上,Android Things 已经帮我们把读写接口封装好了,我们只需要在理解的基础上,调用接口就行了。
可以看出, I2C 的读写操作 Android Things 已经给我们封装好了,我们直接用就可以了。
这里面还有个细节比较绕。之前提到, I2C 的设备地址可以是 7 位,也可以是 10 位,但是 I2C 设备的寄存器可以是 8 位,也可以是 16 位。这里面就涉及到 8 位的设备,以及 16 位设备的读写问题。
六大函数出场:
8 位地址读写操作- readRegByte() 和 writeRegByte()
16 位地址读写操作 – readRegWord() 和 writeRegWord()
批量读写操作- readRegBuffer() and writeRegBuffer()
其中 Byte 是针对 8 位的 I2C 设备,Word 是针对 16 位的设备。
读操作:用寄存器的地址做为参数。
写操作:两个参数,寄存器地址,和你要写入的值。
上面的代码中,把寄存器的第 6 位置 1。所以操作流程是
读出寄存器的值
将这个值的第6位置1 (value |= 0x40;)
然后把新的值写回寄存器
不过对于 16 位的地址操作还有一个大小端的问题。(什么是大小端?去 Google 吧 )现在的 API 是依照小端模式来读写的 16 位设备地址。
直接批量数据操作,可以最大读到32个连续的寄存器的数值。
那么,我们怎么使用接口进行批量操作呢?
传输原始数据
还是先来张图吧:
这种操作方法,不同于上面的读写寄存器。在 I2C 的操作中,属于 burst 操作方法。即一次性的读写多少字节,最后再停止。
跟一个例子:
这样传输能带来更高的传输效率。解决了 I2C 传输的核心问题,我们也解决了支持 I2C 的任何外设的读写问题。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=2075,转载请注明出处。
评论0