历史上的今天
今天是:2024年08月30日(星期五)
2019年08月30日 | S5PV210开发 -- I2C 你知道多少?(三)
2019-08-30 来源:eefocus
I2C部分已经接近尾声了,接下来我们回过头来看一下剩下的一些小知识点。如 I2C 仲裁、Linux I2C 工具查看配置I2C设备、什么是漏极开路等等。
一、动手画出I2C时序图
看了那么多东西,都记不牢的或者理解不透。只有亲自画出时序图,你才能明白的。
就画 MT9P031 写操作,设备写地址为0xBA,片内寄存器地址为0x09,发送数据 0000 0010 和 1000 0100

我只画了起始位、设备写地址为0xBA、ACK 这几部分,详细的看下图。

当你画的时候,你就会注意到I2C协议的一些知识了:
1、SCL 为低电平,SDA 可以进行修改;
2、SCL 为高电平,SDA 保持稳定不变;
3、SCL 为高电平时,如果 SDA 有变动则视为特殊状况:启动(启始,SDA 由高转为低)或停止(结束,SDA 由低转为高)。
上面三条定义刚好把SCL和SDA三条讯号线会发生的讯号全部都包括了。
4、除了Start(启始)和Stop(结束)二个讯号之外,所有的信号传输固定8 bits(1 字节)为一组,这一个字节可能是一个设备地址,寄存器地址或写入或读取从机的数据,数据首先传输最高有效位(MSB)。
5、发送端在每组(8位)信号发出后,需读取接收端所回应的一个 ACK 位(信号为低)或 NACK 位(信号为高)。 (注意:发送端不一定是master。例如:读取资料时,发送端为slave)。
6、设备地址读/写位,0 表示主设备向从设备写数据,1 表示主设备向从设备读数据。
以AT24C02存储器为例:
通过芯片手册,得到设备地址相关的内容:
1010A2A1A0R/W:设备地址不包含读写位,右移1位,高位补0 =》 01010A2A1A0(A2A1A0都接地)=01010000=》AT24C02在开发板上的设备地址为0x50
读设备地址 = 设备地址 << 1 | 读写位(1) = 0xA1
写设备地址 = 设备地址 << 1 | 读写位(0) = 0xA0
二、I2C仲裁机制

我们晓得 I2C 允许多个主设备和多个从设备。如果两个或两个以上的主设备同时向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是 I2C 总线上的仲裁。
I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。
(1)同步
所有主机在 SCL 线上产生它们自己的时钟来传输 I2C 总线上的报文。数据只在时钟的高电平周期有效。因此,需要一个确定的时钟进行逐位仲裁。
时钟同步通过 线“与”(Wired-AND)连接 I2C 接口到 SCL 线来执行。这就是说: SCL 线的高到低切换会使器件开始数它们的低电平周期,而且一旦器件的时钟变低电平,它会使 SCL 线保持这种状态直到到达时钟的高电平。但是,如果另一个时钟仍处于低电平周期,这个时钟的低到高切换不会改变 SCL 线的状态。因此,SCL 线被有最长低电平周期的器件保持低电平。此时,低电平周期短的器件会进入高电平的等待状态。

当所有有关的器件数完了它们的低电平周期后,时钟线被释放并变成高电平。之后,器件时钟和 SCL 线的状态没有差别。而且所有器件会开始数它们的高电平周期。首先完成高电平周期的器件会再次将 SCL 线拉低。
这样,产生的同步 SCL 时钟的低电平周期由低电平时钟周期最长的器件决定,而高电平周期由高电平时钟周期最短的器件决定。
(2)仲裁
主机只能在总线空闲的时侯启动传输。两个或多个主机可能在起始条件的最小持续时间(tHD;STA)内产生一个起始条件,结果在总线上产生一个规定的起始条件。
当 SCL 线是高电平时,仲裁在 SDA 线发生;这样,在其他主机发送低电平时,发送高电平的主机将断开它的数据输出级,因为总线上的电平与它自己的电平不相同。
仲裁可以持续多位。它的第一个阶段是比较地址位。如果每个主机都尝试寻址相同的器件,仲裁会继续比较数据位(如果是主机-发送器)或者比较响应位(如果是主机-接收器)。因为 I2C 总线的地址和数据信息由赢得仲裁的主机决定,在仲裁过程中不会丢失信息。丢失仲裁的主机可以产生时钟脉冲直到丢失仲裁的该字节末尾。
由于 Hs 模式的主机有一个唯一的 8 位主机码,因此一般在第一个字节就可以结束仲裁。如果主机也结合了从机功能 而且在寻址阶段丢失仲裁,它很可能就是赢得仲裁的主机在寻址的器件。因此,丢失仲裁的主机必须立即切换到它的从机模式。
下图显示了两个主机的仲裁过程。当然,可能包含更多的内容(由连接到总线的主机数量决定)。此时,产生 DATA1 的主机的内部数据电平与 SDA 线的实际电平有一些差别,如果关断数据输出,这就意味着总线连接了一个高输出电平。这不会影响由赢得仲裁的主机初始化的数据传输。

由于 I2C 总线的控制只由地址或主机码以及竞争主机发送的数据决定,没有中央主机,总线也没有任何定制的优先权。
必须特别注意的是:在串行传输时,当重复起始条件或停止条件发送到 I2C 总线的时侯,仲裁过程仍在进行。如果可能产生这样的情况,有关的主机必须在帧格式相同位置发送这个重复起始条件或停止条件。也就是说,仲裁不能在下面的情况之间进行:
1、重复起始条件和数据位
2、停止条件和数据位
3、重复起始条件和停止条件
4、从机不被卷入仲裁过程
I2C 仲裁机制,理解了 线“与”(Wired-AND),就一目了然了。
或者再简单说,它遵循“低电平优先”的原则,即谁先发送低电平谁就会掌握对总线的控制权。
三、Linux I2C 工具查看配置I2C设备
(1)下载安装
参看:i2c-tools -- 维基百科
i2c-tools软件包包含一组用于Linux的异构I2C工具:
总线探测工具,芯片翻转器,寄存器级SMBus访问助手,EEPROM解码脚本,EEPROM编程工具以及用于SMBus访问的python模块。 只要内核包含I2C支持,所有版本的Linux都受支持。
下载:i2c-tools 下载
修改 Makefile ,编译器改为交叉编译:
COMPILE_PREFIX := /home/tarena/esd1503/arm-2009q3/bin/
CC := $(COMPILE_PREFIX)arm-none-linux-gnueabi-gcc
AR := $(COMPILE_PREFIX)arm-none-linux-gnueabi-ar
生成 i2cdetect, i2cdump, i2cget, i2cset,i2ctransfer
使用 file 指令检查一下:
# file i2cdetect
i2cdetect: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped
(2)使用
使用 tftp 将 i2cdetect, i2cdump, i2cget, i2cset,i2ctransfer 拷贝到开发板中。
然后执行 i2cdetect,出现错误:
# ./i2cdetect -l
./i2cdetect: error while loading shared libraries: libi2c.so.0: cannot open shared object file:
No such file or directory
缺少共享库 libi2c.so.0,将i2c-tools-4.0/lib/libi2c.so.0.1.0 拷贝到开发板 lib 目录下,然后增加权限 chmod 777 libi2c.so.0.1.0,然后重命名为 libi2c.so.0。
PS:本来想拷贝libi2c.so.0的,但是它和libi2c.so.0.1.0是硬链接关系,拷贝出现错误。
# stat libi2c.so.0
文件:"libi2c.so.0" -> "libi2c.so.0.1.0"
大小:15 块:0 IO 块:4096 符号链接
设备:801h/2049d Inode:2128654 硬链接:1
权限:(0777/lrwxrwxrwx) Uid:( 0/ root) Gid:( 0/ root)
最近访问:2017-12-20 10:31:47.155123897 +0800
最近更改:2017-12-20 10:24:43.174893417 +0800
最近改动:2017-12-20 10:24:43.174893417 +0800
创建时间:-

然后直接用 libi2c.so.0.1.0 也不行,需要重命名为 libi2c.so.0
到此可以在开发板上执行 i2cdetect:
]# ./i2cdetect -l
i2c-0 i2c s3c2410-i2c I2C adapter
i2c-1 i2c s3c2410-i2c I2C adapter
i2c-2 i2c s3c2410-i2c I2C adapter
(3)详解指令
现在挨个来看一下这些指令都该如何使用。
参看:Configuring_Aptina_MT9P031_using_i2c-tools
因为我购买的 S5PV210 开发板没有 AT24C02 和 S3C2410 芯片,所以没法测试。为了测试,找出尘封了好久的 DM368 开发板,主要看MT9P031。
1、i2cdetect 指令
查看它的选项:
# i2cdetect
Error: No i2c-bus specified!
Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]
i2cdetect -F I2CBUS
i2cdetect -l
I2CBUS is an integer or an I2C bus name
If provided, FIRST and LAST limit the probing range.
首先在你的主板的终端中运行 i2cdetect -l 命令:
# i2cdetect -l
i2c-1 i2c DaVinci I2C adapter I2C adapter
该命令将显示任何可用的I2C总线。而输出的结果告诉我们有一个 I2C 总线,其ID是 i2c-1
一旦获得了I2C总线名称,就可以通过运行 i2cdetect -y I2CBUS 得到总线上都挂载的所有设备的设备地址
其中,I2CBUS 是一个整数或I2C总线名称。
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- 08 -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- UU -- --
60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- UU -- -- -- --
通过,参看:S5PV210开发 -- I2C 你知道多少?(一) 知道 MT9P031 的设备地址为 0x5d。
然后查看下图可以发现 I2C 总线上是有挂载 MT9P031 设备地址的。

如果不确定,那么来做个测试,关闭电源,去除摄像头,然后再次执行 i2cdetect -y 1
结果如下,可以得出 0x5d 就是sensor MT9P031 的设备地址。
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- 08 -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- UU -- -- -- --
2、i2cdump 指令
查看它的选项
# i2cdump
Error: No i2c-bus specified!
Usage: i2cdump [-f] [-y] [-r first-last] I2CBUS ADDRESS [MODE [BANK [BANKREG]]]
I2CBUS is an integer or an I2C bus name
ADDRESS is an integer (0x03 - 0x77)
MODE is one of:
b (byte, default)
w (word)
W (word on even register addresses)
s (SMBus block)
i (I2C block)
c (consecutive byte)
Append p for SMBus PEC
如果想要导出I2C设备中的所有寄存器内容,运行指令 i2cdump -f -y I2CBUS ADDRESS
其中 I2CBUS 是一个整数或I2C总线名称,ADDRESS是一个整数(0x03 - 0x77)。
例如,我们查看 MT9P031的寄存器内容。
# i2cdump -f -y 1 0x5d
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 18 00 00 07 0a 00 00 1f 00 07 80 00 00 00 00 00 ?..??..?.??.....
10: 00 64 00 00 00 00 00 00 00 00 00 00 00 00 40 00 .d............@.
20: 00 00 00 00 00 00 00 00 00 04 10 00 00 00 00 00 .........??.....
30: 00 00 00 00 00 00 00 00 00 00 00 00 12 00 80 00 ............?.?.
40: 00 00 00 00 02 10 10 10 00 00 00 00 00 0e 10 00 ....????.....??.
50: 80 00 80 00 00 00 00 00 80 00 00 00 00 2d 41 23 ?.?.....?....-A#
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 a7 a7 0c 06 56 6b 6b a5 ab a9 a7 a7 ff a9 a9 .????Vkk?????.??
80: 00 1f 00 1b 1d 00 18 1a 00 00 00 00 00 00 00 00 .?.??.??........
90: 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?...............
a0: 00 00 00 00 00 00 00 00 00 00 00 07 0a ca 00 44 ...........???.D
b0: bc 48 be 48 b8 c2 e0 06 01 09 09 09 03 0b 09 08 ?H?H????????????
c0: 02 01 04 06 06 0e 05 0b d2 c4 1a 49 a4 46 b0 60 ???????????I?F?`
d0: 44 08 d0 34 ee 4d 27 92 8d 5e a0 0f 91 24 9c 95 D??4?M'??^???$??
e0: 78 6c 11 d1 b4 13 59 1e 7c ad a1 3e e4 a1 14 13 xl????Y?|??>????
f0: 00 00 00 00 00 00 00 00 00 00 a3 0a 56 71 00 18 ..........??Vq.?
3、i2cget 指令
查看它的选项
# i2cget
Usage: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]
I2CBUS is an integer or an I2C bus name
ADDRESS is an integer (0x03 - 0x77)
MODE is one of:
b (read byte data, default)
w (read word data)
c (write byte/read byte)
Append p for SMBus PEC
上面 i2cdump 是读取所有寄存器的内容,那么如果只是想要读取特定寄存器的内容呢。
运行指令 i2cget -f -y I2CBUS CHIP-ADDRESS MODE
其中 I2CBUS 是一个整数或 I2C 总线名称,ADDRESS 是一个整数(0x03 - 0x77)。
MODE是以下之一:
b(读取字节数据,默认)
w(读取字数据)
c(写入字节/读取字节)
还是以 MT9P031 为例,我们看它的时序图,片内寄存器地址是 0x09。那我们就看这个寄存器的内容好了。
由于MT9P031有16位寄存器,所以我们必须使用读取字数据(w)。

# i2cget -f -y 1 0x5d 0x09 w
0x9707
我们看到MT9P031的数据表,你会看到正确的芯片版本寄存器的值是0x0284。就算是由于大小端的原因得出的结果最多也会是 0x8402,但是我们得到的却是 0x9707 我就不晓得为什么了。
再举个例子:
# i2cget -f -y 1 0x5d 0x00 w
0x0118
想要查看 MT9P031 的芯片 ID。片内寄存器地址为 0x00,得出的值为 0x0118,大小端转换其结果应为 0x1801.
然后再查看,内核启动信息里的这段话。
mt9p031 1-005d: Detected a MT9P031 chip ID 1801
mt9p031 1-005d: mt9p031 1-005d decoder driver registered !!
vpfe-capture vpfe-capture: v4l2 sub device mt9p031 registered
vpfe_register_ccdc_device: DM365 ISIF
史海拾趣
|
全球汽车半导体面临极大的市场机会,但设计工程师同样面临在成本、功耗、安全性等多方面的技术挑战。本文以可接收和发送数据的最新智能应答器为例,向中国汽车设计工程师介绍了在汽车无线接入系统设计中解决这些挑战的技术方法。 … 查看全部问答> |
|
用“复杂”来形容当今的汽车是再恰当不过的一个词。安全、操控、驱动和娱乐仅仅是依赖电子/电气架构的部分子系统。如今的驾驶者都希望他们的座驾能够无限精准且不间歇地运转。但是控制整个汽车的电子神经系统的内部却是如此的复杂。如今,大部分汽 ...… 查看全部问答> |
|
单片机音乐播放中歌曲的代码怎样弄出来的? 我看了网上的一些教程。。一个个的算很麻烦。。而且我对音乐不熟悉。 这样效率很低。。有没有一些快点的方法? 先在这里谢了~… 查看全部问答> |
|
编程环境:evc 程序的功能:点击按钮弹出对话框 情况说明: 在evc下采用MFC编写应用程序,实现点击按钮button1,弹出对话框,用鼠标点击,没有问题,可以正常运行,点击键盘上的ENTER键(确定),也可以弹出对话框。 由于需要进行按钮美化,将b ...… 查看全部问答> |
|
现在开发一个基于嵌入式的边缘检测系统,大概实现工业领域对产品零件的检测。该系统通过微型工业相机拍摄零件图片。然后对图片中零件进行边缘检测,来标定零件是否合格。 问题: 1.这种方案有无可行性? 2.硬件用ARM还是DSP? 3.有没有相关领域 ...… 查看全部问答> |
|
前面的是个阻容衰减电路,在衰减100倍时,跟随输出时正常的,但衰减10倍的时候跟随输出被放大了,要求10M带宽,实际仿真的时候都正常,但我搭出电路却不是那么回事了,似乎是跟随前的输入阻抗引起的,但跟随的输入阻抗很高,困惑中··· [ 本帖最 ...… 查看全部问答> |
|
最近想DIY一个遥控电源插座,希望大家给个建议:收集了一些资料,但感觉不太满意,如下:PH303A×2红外脉冲发射电路如下图所示,调节RP1,使其振荡频率为12kHz.红外遥控接收电路:… 查看全部问答> |
|
中文名:51单片机应用开发范例大全 作者:宋戈 图书分类:硬件 资源格式:PDF 版本:扫描版 出版社:人民邮电出版社 书号:9787115218322 发行时间:2010年2月 地区:大陆 语言:简体中文简介: 内容简介: 当前,单片机在各个领域的应用十分广 ...… 查看全部问答> |




