S5PV210开发 -- I2C 你知道多少?(三)
如需轉(zhuǎn)載請(qǐng)注明出處:https://blog.csdn.net/qq_29350001/article/details/78835639
I2C部分已經(jīng)接近尾聲了,接下來(lái)我們回過(guò)頭來(lái)看一下剩下的一些小知識(shí)點(diǎn)。如 I2C 仲裁、Linux I2C 工具查看配置I2C設(shè)備、什么是漏極開(kāi)路等等。
一、動(dòng)手畫(huà)出I2C時(shí)序圖
看了那么多東西,都記不牢的或者理解不透。只有親自畫(huà)出時(shí)序圖,你才能明白的。
就畫(huà) MT9P031 寫(xiě)操作,設(shè)備寫(xiě)地址為0xBA,片內(nèi)寄存器地址為0x09,發(fā)送數(shù)據(jù) 0000 0010 和 1000 0100
、
我只畫(huà)了起始位、設(shè)備寫(xiě)地址為0xBA、ACK 這幾部分,詳細(xì)的看下圖。
?
當(dāng)你畫(huà)的時(shí)候,你就會(huì)注意到I2C協(xié)議的一些知識(shí)了:
1、SCL 為低電平,SDA 可以進(jìn)行修改;
2、SCL 為高電平,SDA 保持穩(wěn)定不變;
3、SCL 為高電平時(shí),如果 SDA 有變動(dòng)則視為特殊狀況:啟動(dòng)(啟始,SDA 由高轉(zhuǎn)為低)或停止(結(jié)束,SDA 由低轉(zhuǎn)為高)。?
上面三條定義剛好把SCL和SDA三條訊號(hào)線會(huì)發(fā)生的訊號(hào)全部都包括了。
4、除了Start(啟始)和Stop(結(jié)束)二個(gè)訊號(hào)之外,所有的信號(hào)傳輸固定8 bits(1 字節(jié))為一組,這一個(gè)字節(jié)可能是一個(gè)設(shè)備地址,寄存器地址或?qū)懭牖蜃x取從機(jī)的數(shù)據(jù),數(shù)據(jù)首先傳輸最高有效位(MSB)。
5、發(fā)送端在每組(8位)信號(hào)發(fā)出后,需讀取接收端所回應(yīng)的一個(gè) ACK 位(信號(hào)為低)或 NACK 位(信號(hào)為高)。 (注意:發(fā)送端不一定是master。例如:讀取資料時(shí),發(fā)送端為slave)。
6、設(shè)備地址讀/寫(xiě)位,0 表示主設(shè)備向從設(shè)備寫(xiě)數(shù)據(jù),1 表示主設(shè)備向從設(shè)備讀數(shù)據(jù)。
以AT24C02存儲(chǔ)器為例:
通過(guò)芯片手冊(cè),得到設(shè)備地址相關(guān)的內(nèi)容:
? 1010A2A1A0R/W:設(shè)備地址不包含讀寫(xiě)位,右移1位,高位補(bǔ)0?=》?01010A2A1A0(A2A1A0都接地)=01010000=》AT24C02在開(kāi)發(fā)板上的設(shè)備地址為0x50
? 讀設(shè)備地址 = 設(shè)備地址 << 1 | 讀寫(xiě)位(1) = 0xA1
? 寫(xiě)設(shè)備地址 = 設(shè)備地址 << 1 | 讀寫(xiě)位(0) = 0xA0
二、I2C仲裁機(jī)制
?
我們曉得 I2C 允許多個(gè)主設(shè)備和多個(gè)從設(shè)備。如果兩個(gè)或兩個(gè)以上的主設(shè)備同時(shí)向總線上發(fā)送啟動(dòng)信號(hào)并開(kāi)始傳送數(shù)據(jù),這樣就形成了沖突。要解決這種沖突,就要進(jìn)行仲裁的判決,這就是 I2C 總線上的仲裁。
?
I2C總線上的仲裁分兩部分:SCL線的同步和SDA線的仲裁。
?
(1)同步
所有主機(jī)在 SCL 線上產(chǎn)生它們自己的時(shí)鐘來(lái)傳輸 I2C 總線上的報(bào)文。數(shù)據(jù)只在時(shí)鐘的高電平周期有效。因此,需要一個(gè)確定的時(shí)鐘進(jìn)行逐位仲裁。
時(shí)鐘同步通過(guò)?線“與”(Wired-AND)連接 I2C 接口到 SCL 線來(lái)執(zhí)行。這就是說(shuō): SCL 線的高到低切換會(huì)使器件開(kāi)始數(shù)它們的低電平周期,而且一旦器件的時(shí)鐘變低電平,它會(huì)使 SCL 線保持這種狀態(tài)直到到達(dá)時(shí)鐘的高電平。但是,如果另一個(gè)時(shí)鐘仍處于低電平周期,這個(gè)時(shí)鐘的低到高切換不會(huì)改變 SCL 線的狀態(tài)。因此,SCL 線被有最長(zhǎng)低電平周期的器件保持低電平。此時(shí),低電平周期短的器件會(huì)進(jìn)入高電平的等待狀態(tài)。
當(dāng)所有有關(guān)的器件數(shù)完了它們的低電平周期后,時(shí)鐘線被釋放并變成高電平。之后,器件時(shí)鐘和 SCL 線的狀態(tài)沒(méi)有差別。而且所有器件會(huì)開(kāi)始數(shù)它們的高電平周期。首先完成高電平周期的器件會(huì)再次將 SCL 線拉低。
這樣,產(chǎn)生的同步 SCL 時(shí)鐘的低電平周期由低電平時(shí)鐘周期最長(zhǎng)的器件決定,而高電平周期由高電平時(shí)鐘周期最短的器件決定。
(2)仲裁
主機(jī)只能在總線空閑的時(shí)侯啟動(dòng)傳輸。兩個(gè)或多個(gè)主機(jī)可能在起始條件的最小持續(xù)時(shí)間(tHD;STA)內(nèi)產(chǎn)生一個(gè)起始條件,結(jié)果在總線上產(chǎn)生一個(gè)規(guī)定的起始條件。
當(dāng) SCL 線是高電平時(shí),仲裁在 SDA 線發(fā)生;這樣,在其他主機(jī)發(fā)送低電平時(shí),發(fā)送高電平的主機(jī)將斷開(kāi)它的數(shù)據(jù)輸出級(jí),因?yàn)榭偩€上的電平與它自己的電平不相同。
仲裁可以持續(xù)多位。它的第一個(gè)階段是比較地址位。如果每個(gè)主機(jī)都嘗試尋址相同的器件,仲裁會(huì)繼續(xù)比較數(shù)據(jù)位(如果是主機(jī)-發(fā)送器)或者比較響應(yīng)位(如果是主機(jī)-接收器)。因?yàn)?I2C 總線的地址和數(shù)據(jù)信息由贏得仲裁的主機(jī)決定,在仲裁過(guò)程中不會(huì)丟失信息。丟失仲裁的主機(jī)可以產(chǎn)生時(shí)鐘脈沖直到丟失仲裁的該字節(jié)末尾。
由于 Hs 模式的主機(jī)有一個(gè)唯一的 8 位主機(jī)碼,因此一般在第一個(gè)字節(jié)就可以結(jié)束仲裁。如果主機(jī)也結(jié)合了從機(jī)功能 而且在尋址階段丟失仲裁,它很可能就是贏得仲裁的主機(jī)在尋址的器件。因此,丟失仲裁的主機(jī)必須立即切換到它的從機(jī)模式。
下圖顯示了兩個(gè)主機(jī)的仲裁過(guò)程。當(dāng)然,可能包含更多的內(nèi)容(由連接到總線的主機(jī)數(shù)量決定)。此時(shí),產(chǎn)生 DATA1 的主機(jī)的內(nèi)部數(shù)據(jù)電平與 SDA 線的實(shí)際電平有一些差別,如果關(guān)斷數(shù)據(jù)輸出,這就意味著總線連接了一個(gè)高輸出電平。這不會(huì)影響由贏得仲裁的主機(jī)初始化的數(shù)據(jù)傳輸。
由于 I2C 總線的控制只由地址或主機(jī)碼以及競(jìng)爭(zhēng)主機(jī)發(fā)送的數(shù)據(jù)決定,沒(méi)有中央主機(jī),總線也沒(méi)有任何定制的優(yōu)先權(quán)。
必須特別注意的是:在串行傳輸時(shí),當(dāng)重復(fù)起始條件或停止條件發(fā)送到 I2C 總線的時(shí)侯,仲裁過(guò)程仍在進(jìn)行。如果可能產(chǎn)生這樣的情況,有關(guān)的主機(jī)必須在幀格式相同位置發(fā)送這個(gè)重復(fù)起始條件或停止條件。也就是說(shuō),仲裁不能在下面的情況之間進(jìn)行:
1、重復(fù)起始條件和數(shù)據(jù)位
2、停止條件和數(shù)據(jù)位
3、重復(fù)起始條件和停止條件
4、從機(jī)不被卷入仲裁過(guò)程
?
I2C 仲裁機(jī)制,理解了?線“與”(Wired-AND),就一目了然了。
或者再簡(jiǎn)單說(shuō),它遵循“低電平優(yōu)先”的原則,即誰(shuí)先發(fā)送低電平誰(shuí)就會(huì)掌握對(duì)總線的控制權(quán)。
三、Linux I2C 工具查看配置I2C設(shè)備
(1)下載安裝
參看:i2c-tools -- 維基百科
i2c-tools軟件包包含一組用于Linux的異構(gòu)I2C工具:
總線探測(cè)工具,芯片翻轉(zhuǎn)器,寄存器級(jí)SMBus訪問(wèn)助手,EEPROM解碼腳本,EEPROM編程工具以及用于SMBus訪問(wèn)的python模塊。 只要內(nèi)核包含I2C支持,所有版本的Linux都受支持。
下載:i2c-tools 下載
修改 Makefile ,編譯器改為交叉編譯:
?
COMPILE_PREFIX := /home/tarena/esd1503/arm-2009q3/bin/CC := $(COMPILE_PREFIX)arm-none-linux-gnueabi-gccAR := $(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 拷貝到開(kāi)發(fā)板中。
然后執(zhí)行 i2cdetect,出現(xiàn)錯(cuò)誤:
?
# ./i2cdetect -l ./i2cdetect: error while loading shared libraries: libi2c.so.0: cannot open shared object file: No such file or directory缺少共享庫(kù)?libi2c.so.0,將i2c-tools-4.0/lib/libi2c.so.0.1.0 拷貝到開(kāi)發(fā)板 lib 目錄下,然后增加權(quán)限 chmod 777?libi2c.so.0.1.0,然后重命名為?libi2c.so.0。
?
PS:本來(lái)想拷貝libi2c.so.0的,但是它和libi2c.so.0.1.0是硬鏈接關(guān)系,拷貝出現(xiàn)錯(cuò)誤。
?
# stat libi2c.so.0文件:"libi2c.so.0" -> "libi2c.so.0.1.0"大小:15 塊:0 IO 塊:4096 符號(hào)鏈接 設(shè)備:801h/2049d Inode:2128654 硬鏈接:1 權(quán)限:(0777/lrwxrwxrwx) Uid:( 0/ root) Gid:( 0/ root) 最近訪問(wèn):2017-12-20 10:31:47.155123897 +0800 最近更改:2017-12-20 10:24:43.174893417 +0800 最近改動(dòng):2017-12-20 10:24:43.174893417 +0800 創(chuàng)建時(shí)間:-然后直接用?libi2c.so.0.1.0 也不行,需要重命名為?libi2c.so.0
?
到此可以在開(kāi)發(fā)板上執(zhí)行 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)詳解指令
現(xiàn)在挨個(gè)來(lái)看一下這些指令都該如何使用。
參看:Configuring_Aptina_MT9P031_using_i2c-tools
因?yàn)槲屹?gòu)買(mǎi)的 S5PV210 開(kāi)發(fā)板沒(méi)有 AT24C02 和 S3C2410 芯片,所以沒(méi)法測(cè)試。為了測(cè)試,找出塵封了好久的 DM368 開(kāi)發(fā)板,主要看MT9P031。
1、i2cdetect 指令
查看它的選項(xiàng):
# i2cdetect Error: No i2c-bus specified! Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]i2cdetect -F I2CBUSi2cdetect -lI2CBUS is an integer or an I2C bus nameIf provided, FIRST and LAST limit the probing range.?
首先在你的主板的終端中運(yùn)行 i2cdetect -l 命令:
# i2cdetect -l i2c-1 i2c DaVinci I2C adapter I2C adapter該命令將顯示任何可用的I2C總線。而輸出的結(jié)果告訴我們有一個(gè) I2C 總線,其ID是 i2c-1
?
一旦獲得了I2C總線名稱,就可以通過(guò)運(yùn)行 i2cdetect -y I2CBUS?得到總線上都掛載的所有設(shè)備的設(shè)備地址
其中,I2CBUS?是一個(gè)整數(shù)或I2C總線名稱。
# i2cdetect -y 10 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 -- -- -- --?
通過(guò),參看:S5PV210開(kāi)發(fā) -- I2C 你知道多少?(一)?知道 MT9P031 的設(shè)備地址為 0x5d。
然后查看下圖可以發(fā)現(xiàn) I2C 總線上是有掛載 MT9P031 設(shè)備地址的。
?
如果不確定,那么來(lái)做個(gè)測(cè)試,關(guān)閉電源,去除攝像頭,然后再次執(zhí)行 i2cdetect -y 1
結(jié)果如下,可以得出 0x5d 就是sensor MT9P031 的設(shè)備地址。
# i2cdetect -y 10 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 指令
查看它的選項(xiàng)
# 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 nameADDRESS 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
如果想要導(dǎo)出I2C設(shè)備中的所有寄存器內(nèi)容,運(yùn)行指令 i2cdump -f -y I2CBUS ADDRESS
其中 I2CBUS 是一個(gè)整數(shù)或I2C總線名稱,ADDRESS是一個(gè)整數(shù)(0x03 - 0x77)。
例如,我們查看 MT9P031的寄存器內(nèi)容。
# 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 指令
查看它的選項(xiàng)
# i2cget Usage: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]I2CBUS is an integer or an I2C bus nameADDRESS 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 是讀取所有寄存器的內(nèi)容,那么如果只是想要讀取特定寄存器的內(nèi)容呢。
運(yùn)行指令 i2cget -f -y I2CBUS CHIP-ADDRESS MODE
其中 I2CBUS 是一個(gè)整數(shù)或 I2C 總線名稱,ADDRESS 是一個(gè)整數(shù)(0x03 - 0x77)。
MODE是以下之一:
? ? ?b(讀取字節(jié)數(shù)據(jù),默認(rèn))
? ? ?w(讀取字?jǐn)?shù)據(jù))
? ? ?c(寫(xiě)入字節(jié)/讀取字節(jié))
還是以 MT9P031 為例,我們看它的時(shí)序圖,片內(nèi)寄存器地址是 0x09。那我們就看這個(gè)寄存器的內(nèi)容好了。
由于MT9P031有16位寄存器,所以我們必須使用讀取字?jǐn)?shù)據(jù)(w)。
?
# i2cget -f -y 1 0x5d 0x09 w 0x9707我們看到MT9P031的數(shù)據(jù)表,你會(huì)看到正確的芯片版本寄存器的值是0x0284。就算是由于大小端的原因得出的結(jié)果最多也會(huì)是 0x8402,但是我們得到的卻是 0x9707 我就不曉得為什么了。
?
再舉個(gè)例子:
# i2cget -f -y 1 0x5d 0x00 w 0x0118想要查看 MT9P031 的芯片 ID。片內(nèi)寄存器地址為 0x00,得出的值為 0x0118,大小端轉(zhuǎn)換其結(jié)果應(yīng)為 0x1801.
然后再查看,內(nèi)核啟動(dòng)信息里的這段話。
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 DM365 ISIF is registered with vpfe.發(fā)現(xiàn) MT9P031的chip ID 確實(shí)是 1801。
4、i2cset 指令
查看它的選項(xiàng)
# i2cset Usage: i2cset [-f] [-y] [-m MASK] I2CBUS CHIP-ADDRESS DATA-ADDRESS [VALUE] [MODE]I2CBUS is an integer or an I2C bus nameADDRESS is an integer (0x03 - 0x77)MODE is one of:c (byte, no value)b (byte data, default)w (word data)Append p for SMBus PEC
如果你想在特定的寄存器內(nèi)容寫(xiě)入呢?運(yùn)行指令?i2cset -f -y I2CBUS CHIP-ADDRESS VALUE MODE
其中?I2CBUS 是一個(gè)整數(shù)或 I2C 總線名稱,ADDRESS 是一個(gè)整數(shù)(0x03 - 0x77),VALUE是要寫(xiě)入寄存器的值。
MODE是以下之一:
? ? ?b(讀取字節(jié)數(shù)據(jù),默認(rèn))
? ? ?w(讀取字?jǐn)?shù)據(jù))
? ? ?c(寫(xiě)入字節(jié)/讀取字節(jié))
?
我們將 MT9P031 片內(nèi)寄存器 0x09, 以讀取字?jǐn)?shù)據(jù)(w),這次我們寫(xiě)入正確的值 0x0284。
# i2cset -f -y 1 0x5d 0x09 0x8402 w再讀取: # i2cget -f -y 1 0x5d 0x09 w 0x8402說(shuō)明可以內(nèi)容寫(xiě)入的,重啟開(kāi)發(fā)板發(fā)現(xiàn)數(shù)據(jù)沒(méi)有被重置,依舊是 0x8402 。
?
再舉個(gè)例子:
之前我的DM368開(kāi)發(fā)板主頻為270Mhz,CVDD電壓為1.2V,而只有當(dāng)電壓為1.35v才能實(shí)現(xiàn)主頻為432Mhz。
我用的電源管理芯片是TVP65023RSB,這個(gè)芯片該如何配置,使其生成1.35v呢?
查看芯片手冊(cè),如下這段話,得出TVP65023 的設(shè)備地址為 0x48
The TPS65023 has a 7-bit address:?1001000, other addresses are available upon contact with the factory # 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 -- -- -- --?
然后繼續(xù)查看芯片手冊(cè):
?
通過(guò)i2ctool修改寄存器: 主要有關(guān)的寄存器為05和06如下圖:
i2cset -f -y 1 0x48 0x05 0x80
i2cset -f -y 1 0x48 0x06 0x16
ok!!! ? 有電壓1.35v。
到這步又有問(wèn)題了,通過(guò)I2Ctool可以獲得1.35v,但是掉電后會(huì)恢復(fù)默認(rèn)的1.2v。
所以最后還是更改硬件電路實(shí)現(xiàn)的。
(4)Linux 下 i2c 的其他操作
查看 i2c-1總線:
/sys/devices/platform/i2c_davinci.1/i2c-1# ls 1-001b 1-0049 1-0073 name 1-0025 1-0050 delete_device new_device 1-002c 1-005d device subsystem 1-0039 1-0068 i2c-dev uevent然后進(jìn)入 1-005d 目錄,查看 name:
/sys/devices/platform/i2c_davinci.1/i2c-1/1-005d# ls driver ? ? modalias ? name ? ? ? subsystem ?uevent/sys/devices/platform/i2c_davinci.1/i2c-1/1-005d# cat name mt9p031查看I2C設(shè)備:
/sys/bus/i2c/drivers# ls PCA9543A dummy rtc-ds1307 tvp514x aic3x I2C Codec mt9p031 ths7303 dev_driver pcf857x tps65023我這個(gè)只有一個(gè) i2c-1 總線,如果是多個(gè)總線的話,通過(guò)這種方法就可以知道從設(shè)備是在哪個(gè)總線上了。
(當(dāng)然文件系統(tǒng)不一樣,可能位置也不同,僅供參考)
四、漏極開(kāi)路
我們知道?I2C 器件連接到總線輸出級(jí)必須是集電極開(kāi)路或漏極開(kāi)路形式才能實(shí)現(xiàn)線“與”的邏輯功能。
那么問(wèn)題來(lái)了,什么是漏極開(kāi)路或者集電極開(kāi)路呢?
之前簡(jiǎn)單介紹過(guò)三極管,參看:S5PV210開(kāi)發(fā) -- 驅(qū)動(dòng)開(kāi)發(fā)相關(guān)硬件簡(jiǎn)介
再參看:如何正確的理解漏極開(kāi)路輸出跟推挽輸出? —— 知乎
再參看:集電極開(kāi)路 -- 維基百科
(1)推挽(push-pull)輸出
要理解推挽輸出,首先要理解好三極管(晶體管)的原理。下面這種三極管有三個(gè)端口,分別是基極(Base)、集電極(Collector)和發(fā)射極(Emitter)。下圖是NPN型晶體管。
這種三極管是電流控制型元器件,注意關(guān)鍵詞電流控制。意思就是說(shuō),只要基極B有輸入(或輸出)電流就可以對(duì)這個(gè)晶體管進(jìn)行控制了。
下面請(qǐng)?jiān)试S我換一下概念,把基極B視為控制端,集電極C視為輸入端,發(fā)射極E視為輸出端。這里輸入輸出是指電流流動(dòng)的方向。
當(dāng)控制端有電流輸入的時(shí)候,就會(huì)有電流從輸入端進(jìn)入并從輸出端流出。
而PNP管正好相反,當(dāng)有電流從控制端流出時(shí),就會(huì)有電流從輸入端流到輸出端。
那么推挽電路:
上面的三極管是N型三極管,下面的三極管是P型三極管,請(qǐng)留意控制端、輸入端和輸出端。
當(dāng)Vin電壓為V+時(shí),上面的N型三極管控制端有電流輸入,Q3導(dǎo)通,于是電流從上往下通過(guò),提供電流給負(fù)載。
經(jīng)過(guò)上面的N型三極管提供電流給負(fù)載(Rload),這就叫「推」。
當(dāng)Vin電壓為V-時(shí),下面的三極管有電流流出,Q4導(dǎo)通,有電流從上往下流過(guò)。
經(jīng)過(guò)下面的P型三極管提供電流給負(fù)載(Rload),這就叫「挽」。
以上,這就是推挽(push-pull)電路。
(2)漏極開(kāi)路(Open-Drain)
要理解開(kāi)漏,可以先理解開(kāi)集。
如圖,開(kāi)集(Open Collector)的意思,就是集電極C一端什么都不接,直接作為輸出端口。
如果要用這種電路帶一個(gè)負(fù)載,比如一個(gè)LED,必須接一個(gè)上拉電阻(Pull up 電阻),就像這樣。
當(dāng)Vin沒(méi)有電流,Q5斷開(kāi)時(shí),LED亮。
當(dāng)Vin流入電流,Q5導(dǎo)通時(shí),LED滅。
開(kāi)漏電路,就是把上圖中的三極管換成場(chǎng)效應(yīng)管(MOSFET)。
N型場(chǎng)效應(yīng)管各個(gè)端口的名稱:
場(chǎng)效應(yīng)管是電壓控制型元器件,只要對(duì)柵極施加電壓,DS就會(huì)導(dǎo)通。結(jié)型場(chǎng)效應(yīng)管有一個(gè)特性就是它的輸入阻抗非常大,這意味著:沒(méi)有電流從控制電路流出,也沒(méi)有電流進(jìn)入控制電路。沒(méi)有電流流入或流出,就不會(huì)燒壞控制電路。而雙極型晶體管不同,是電流控制性元器件,如果使用開(kāi)集電路,可能會(huì)燒壞控制電路。這大概就是我們總是聽(tīng)到開(kāi)漏電路而很少聽(tīng)到開(kāi)集電路的原因吧?因?yàn)殚_(kāi)集電路被淘汰了。
(3)、I2C電氣特性
那我們現(xiàn)在分析一下 I2C 的電氣特性。
參看:Understanding the I 2C Bus
I2C在同一條線上使用一個(gè)漏極開(kāi)路/集電極開(kāi)路的輸入緩沖器,從而允許一條數(shù)據(jù)線 用于雙向數(shù)據(jù)流。
1、雙向通信的開(kāi)漏?
漏極開(kāi)路指的是一種輸出,它可以將總線拉低到一個(gè)電壓(接地),或者“釋放”總線,并通過(guò)一個(gè)上拉電阻來(lái)拉起它。 如果總線在由主機(jī)或從機(jī)釋放,線上的上拉電阻(Rpu)負(fù)責(zé)拉總線電壓直至電源軌。 由于沒(méi)有設(shè)備可能會(huì)迫使一個(gè)高線,這意味著總線永遠(yuǎn)不會(huì)遇到一個(gè)通信問(wèn)題,一個(gè)設(shè)備可能試圖發(fā)送一個(gè)高,另一個(gè)發(fā)送一個(gè)低, 造成短路(電源導(dǎo)軌接地)。 I2C 要求如果多主環(huán)境中的主設(shè)備傳輸一個(gè)高,但看到的線路是低的(另一個(gè)設(shè)備拉下來(lái)),以停止通信,因?yàn)榱硪慌_(tái)設(shè)備正在使用該總線(這也就是仲裁機(jī)制,線“與”)。推挽接口不允許這種類型的自由,這是一個(gè) I2C 的好處。
上圖顯示了 SDA / SCL 線上從設(shè)備或主設(shè)備內(nèi)部結(jié)構(gòu)的簡(jiǎn)化視圖,由讀取輸入數(shù)據(jù)的緩沖器和下拉式FET來(lái)傳輸數(shù)據(jù)組成。?一個(gè)設(shè)備是只能將總線拉低(提供對(duì)地短路)或釋放總線(高阻接地),并允許上拉電阻提高電壓。?這是處理 I2C 時(shí)要實(shí)現(xiàn)的一個(gè)重要概念,因?yàn)闆](méi)有設(shè)備可以保持高總線。這個(gè)屬性是允許雙向通信發(fā)生。
2、漏極開(kāi)路拉低
如前一節(jié)所述,漏極開(kāi)路設(shè)置可能只會(huì)拉低總線或“釋放”它,并讓一個(gè)電阻拉高。?
下圖顯示了拉低總線電流的流程。?想要傳送一個(gè)邏輯低電平時(shí)將激活下拉FET(場(chǎng)效應(yīng)管),從而提供短路接地,拉低線路。
3、漏極開(kāi)路釋放總線
當(dāng)從設(shè)備或主設(shè)備希望傳輸一個(gè)邏輯高電平時(shí),只能通過(guò)關(guān)閉下拉FET(場(chǎng)效應(yīng)管)來(lái)釋放總線。?這使得總線懸空,上拉電阻將把電壓拉高到電壓軌,這將被解釋為一個(gè)高電平。?下圖顯示了通過(guò)上拉電阻的電流流動(dòng),拉高總線。
?
五、總結(jié)
I2C 總結(jié)用了十多天的時(shí)間,寫(xiě)了三篇文章,可算是講完了,不容易啊。
而且我覺(jué)得講的相當(dāng)細(xì)致了,結(jié)合了之前開(kāi)發(fā)時(shí)需要的問(wèn)題,I2C 的軟硬件都有涉及到。
以后開(kāi)發(fā)再遇到 I2C 通信,絕對(duì)的不用愁了。哈哈...
如需轉(zhuǎn)載請(qǐng)注明出處:https://blog.csdn.net/qq_29350001/article/details/78835639
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的S5PV210开发 -- I2C 你知道多少?(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Hadoop:HDFS的概念理解和体系架
- 下一篇: 最优化学习笔记(十三)——基本共轭方向算