1 簡介
IIC(I2C)是一種同步、多主、多從、分組交換、單端、串行計(jì)算機(jī)總線,由飛利浦半導(dǎo)體(現(xiàn)在的 NXP 半導(dǎo)體)在 1982 年發(fā)明。它廣泛用于在短距離、板內(nèi)通信中將低速外設(shè)集成電路附加到處理器和微控制器上。
1.1 拓?fù)浣Y(jié)構(gòu)
I2C 總線有兩根線 SDA/SCL 就可以連一堆芯片,實(shí)現(xiàn)很多的外設(shè)應(yīng)用。
目前, I2C 可以支持以下幾種模式:
雙向總線:
standard-mode(Sm): ≤100 Kbit/S
Fast-Mode(Fm):≤400 Kbit/S
Fast-mode Plus(Fm+):≤1Mbit/S
High-speed mode (Hs-mode): ≤ 3.4 Mbit/s
單向總線:
Ultra Fast-mode (UFm): ≤ 5 Mbit/s
對于不同模式下,拓?fù)涞逆溄哟嬖诓煌?br>標(biāo)準(zhǔn)速度/快速模式:
高速模式拓?fù)?/mark>:
1.2 工作原理
如果使用 IO 口模擬 I2C 總線,或者使用 FPGA 實(shí)現(xiàn) I2C 接口,深刻理解 I2C 時(shí)序波形無疑是重點(diǎn)中的重點(diǎn)!
1.2.1 時(shí)序圖

- START 事件:每個(gè)字節(jié)發(fā)送的過程中都會有一個(gè)啟動(dòng)事件,就是在 SCL 常高時(shí),采集到 SDA 高到低跳變,這就是啟動(dòng)事件
- 數(shù)據(jù)有效性:SDA 線上的數(shù)據(jù)必須在時(shí)鐘的高周期保持穩(wěn)定。數(shù)據(jù)線的高或低狀態(tài)只能在 SCL 線上的時(shí)鐘信號低時(shí)改變。每個(gè)傳輸?shù)臄?shù)據(jù)位產(chǎn)生一個(gè)時(shí)鐘脈沖。所以時(shí)鐘線的高電平比數(shù)據(jù)的有效電平時(shí)間短。
- ACK信號:確認(rèn)信號 ACK 的定義如下:發(fā)送器在 ACK 時(shí)鐘脈沖期間釋放 SDA 線,因此接收器可以將 SDA 線拉低,并在此時(shí)鐘脈沖的高電平期間保持穩(wěn)定的低電平(見上圖)。
- NACK信號:當(dāng)在第九個(gè)時(shí)鐘脈沖期間 SDA 保持高電平時(shí),該數(shù)據(jù)被定義為“NACK”信號。之后主機(jī)可以產(chǎn)生停止條件以中止傳輸,或產(chǎn)生重復(fù)的開始條件以開始新的傳輸。
導(dǎo)致 NACK 產(chǎn)生的條件有五個(gè):
4.1. 總線上沒有報(bào)文中所包含地址的接收器,因此沒有設(shè)備響應(yīng)應(yīng)答。
4.2. 接收器無法執(zhí)行接收或發(fā)送操作,比如它正在執(zhí)行某些實(shí)時(shí)功能,并且尚未準(zhǔn)備好與主 機(jī)進(jìn)行通信。
4.3. 在傳輸過程中,接收器收到應(yīng)用協(xié)議不理解的數(shù)據(jù)或命令。
4.4. 在傳輸期間,接收器無法再接收更多有效數(shù)據(jù)字節(jié)。比如程序或者芯片內(nèi)置緩沖區(qū)已經(jīng)滿了
4.5. 主接收器用 NACK 通知從發(fā)送器結(jié)束傳輸。這是何意呢?比如主設(shè)備已經(jīng)接受到足夠多的數(shù)據(jù),不希望從設(shè)備發(fā)送更多的數(shù)據(jù)時(shí),就可以 NACK 從設(shè)備,這樣從設(shè)備就會停止發(fā)送
1.3 時(shí)鐘同步
兩個(gè)主機(jī)可以同時(shí)開始在空閑總線上進(jìn)行傳輸,并且必須有一種方法來確定控制總線并完成其傳輸?shù)姆椒?。這是通過時(shí)鐘同步和仲裁完成的。在單主機(jī)系統(tǒng)中,不需要時(shí)鐘同步和仲裁。
時(shí)鐘同步是通過 I2C 接口中 SCL 線的線與實(shí)現(xiàn)的。
如何理解呢?
可以看到,上圖中的CLK1和CLK2代表兩個(gè)主機(jī)的時(shí)鐘,SCL代表I2C上的時(shí)鐘線。
- 當(dāng)主機(jī)1的CLK1從高到低變化后,SCL也會從高到低的過渡,此時(shí)總線上的主機(jī)2的CLK2依舊出于高電平,其會開始計(jì)數(shù)SCL的低電平時(shí)間,且一旦主機(jī)2的時(shí)鐘變?yōu)榈蜁r(shí),它就會將 SCL 保持在該狀態(tài),直到變?yōu)楦郀顟B(tài)為止。
- 但是,此時(shí)主機(jī)1的時(shí)鐘仍在其低周期內(nèi),則此時(shí)鐘CLK1如果發(fā)生了從低到高的轉(zhuǎn)變不會改變 SCL 線的狀態(tài)。如果低電平周期較短的主機(jī)1在此期間進(jìn)入高電平,則會進(jìn)入等待狀態(tài)。所以,SCL 線只要當(dāng)主機(jī)1或者2其中一個(gè)處于低電平周期,其就會保持為低電平。這就是多主機(jī)下SCL 線的線與。
- 當(dāng)三者都進(jìn)入高電平后,完成時(shí)鐘同步。第一個(gè)完成其高電平周期的主機(jī)將 SCL 線再次拉低。
1.4 時(shí)鐘仲裁
仲裁與同步類似,僅在系統(tǒng)中使用多個(gè)主機(jī)時(shí)才會涉及到,從站不參與仲裁過程。
所謂仲裁就是在多主機(jī)模式下,哪一個(gè)主機(jī)能獲取介質(zhì)的訪問權(quán)限,獲得權(quán)限的主機(jī)才可以傳輸 I2C 通信報(bào)文。只有在總線空閑時(shí),主機(jī)才可以開始傳輸。兩個(gè)主機(jī)可以在 START 的最小保持時(shí)間內(nèi)產(chǎn)生 START 條件這種情況會導(dǎo)致總線上出現(xiàn)有效的 START 條件。然后需要仲裁以確定哪個(gè)主機(jī)將完成其傳輸。
仲裁是一位一位地進(jìn)行。節(jié)點(diǎn)發(fā)送 1 個(gè)位后,回讀比較總線上所呈現(xiàn)的數(shù)據(jù)與自己發(fā)送的是否一致。是,繼續(xù)發(fā)送;否則,退出競爭。SDA 線的仲裁可以保證 I2C 總線系統(tǒng)在多個(gè)主節(jié)點(diǎn)同時(shí)企圖控制總線時(shí)通信正常進(jìn)行并且數(shù)據(jù)不丟失??偩€系統(tǒng)通過仲裁只允許一個(gè)主節(jié)點(diǎn)可以繼續(xù)占據(jù)總線。
由上圖可以看出,兩個(gè)主機(jī)的仲裁程序是如何進(jìn)行的。再SCL高電平時(shí),DATA1和DATA2都產(chǎn)生了START事件,但是在之后的低三個(gè)時(shí)鐘周期時(shí),DATA1的電平與SDA上的電平不一致,也就是主機(jī)1產(chǎn)生的 DATA1 的內(nèi)部數(shù)據(jù)電平與 SDA 線上的實(shí)際電平之間存在差異,DATA1 輸出將關(guān)閉。從而主機(jī) 1 退出競爭,沒有獲得總線的控制權(quán)。
時(shí)鐘延長:時(shí)鐘延長通過將 SCL 線保持為低電平來暫停事務(wù)。直到再次釋放高電平,事務(wù)才能繼續(xù)。時(shí)鐘延長是可選的,實(shí)際上,大多數(shù)從設(shè)備不包括 SCL 驅(qū)動(dòng)能力,因此它們無法延長時(shí)鐘。
其目的可以理解如下:
在字節(jié)傳輸級別,設(shè)備可能能夠以快速速率接收數(shù)據(jù)字節(jié),但需要更多時(shí)間來存儲接收到的字節(jié)或準(zhǔn)備另一個(gè)要發(fā)送的字節(jié)。此時(shí),從機(jī)可以在接收和確認(rèn)字節(jié)后將 SCL 線保持為 LOW,以強(qiáng)制主機(jī)進(jìn)入等待狀態(tài),直到從機(jī)為握手過程中的下一個(gè)字節(jié)傳輸做好準(zhǔn)備。
在位級別上,諸如微控制器之類的設(shè)備可以通過延長每個(gè)時(shí)鐘的 LOW 周期來減慢總線時(shí)鐘。任何主機(jī)的速度都將根據(jù)該設(shè)備的內(nèi)部工作速率進(jìn)行調(diào)整。
1.5 起始 START 字節(jié)
在一個(gè)多設(shè)備用 I2C 總線連一起的系統(tǒng),其中一個(gè)設(shè)備(單片機(jī))使用用 IO 口模擬I2C ,另一個(gè)設(shè)備使用硬件I2C,那么快速的硬件設(shè)備與依賴軟件輪詢的相對較慢的設(shè)備之間必然會存在速度差異。那么依賴軟件輪詢的設(shè)備在通信速率較高的情況下檢測 START 條件信號就有可能丟失,導(dǎo)致系統(tǒng)不健壯。
起始字節(jié)就是用來解決這個(gè)問題。
當(dāng)需要訪問總線的主機(jī)發(fā)送 START 事件,不過其發(fā)送 START 字節(jié)并不是一個(gè)電平變化,而是一個(gè)字節(jié)(0000 0001)。另一個(gè)單片機(jī)/DSP 可以用低采樣率對 SDA 線進(jìn)行采樣,直到檢測到 START 字節(jié)中的七個(gè)零中的一個(gè)為止。
1.6 總線復(fù)位
在異常情況下,如果 SCL或者SDA 被拉為 LOW ,如何進(jìn)行總線復(fù)位呢?
- 如 I2C 設(shè)備具有硬件復(fù)位輸入,則使用硬件復(fù)位信號來復(fù)位總線??隙▋?yōu)先選擇。
- 如果 I2C 設(shè)備沒有硬件復(fù)位輸入信號,可以考慮用 MOSFET 控制設(shè)備電源,重新通電以激活強(qiáng)制性的內(nèi)部上電復(fù)位(POR)電路。
- 還有一種做法是主機(jī)發(fā)送 9 個(gè)時(shí)鐘 SCL 脈沖。使總線保持低電平的設(shè)備應(yīng)在這九個(gè)時(shí)鐘內(nèi)的某個(gè)時(shí)間釋放它。這個(gè)具體怎么做呢?主設(shè)備初始化 I2C 總線時(shí),可以冗余加 9 個(gè) SCL 脈沖以復(fù)位 I2C 總線,或者檢測到 SDA 長時(shí)間被拉低后,可以以控制 IO 高低翻轉(zhuǎn)的方式控制 SCL 產(chǎn)生 9 個(gè)脈沖。不過前提是拉死 SCL 的設(shè)備需要支持這種功能,如果兩端都是自定義開發(fā)的則比較靈活了。
1.7 總線鎖死
在正常情況下,I2C總線協(xié)議能夠保證總線正常的讀寫操作。但是,當(dāng)I2C主設(shè)備異常復(fù)位時(shí)(看門狗動(dòng)作,板上電源異常導(dǎo)致復(fù)位芯片動(dòng)作,手動(dòng)按鈕復(fù)位等等)有可能導(dǎo)致I2C總線死鎖產(chǎn)生。
解決辦法如下:文章來源:http://www.zghlxwxcb.cn/news/detail-488583.html
- 盡量選用帶復(fù)位輸人的I2C從設(shè)備。
- 將所有的從I2C設(shè)備的電源連接在一起,通過MOS管連接到主電源,而MOS管的導(dǎo)通關(guān)斷由I2C主設(shè)備來實(shí)現(xiàn),從而實(shí)現(xiàn)主設(shè)備控制從設(shè)備復(fù)位。
- 在I2C從設(shè)備設(shè)計(jì)看門狗的功能,發(fā)生死鎖問題后,自動(dòng)復(fù)位。
- 1.2.5節(jié)中的復(fù)位方法3。(不太適用)
- 在I2C總線上增加一個(gè)額外的總線恢復(fù)設(shè)備。這個(gè)設(shè)備監(jiān)視I2C總線。當(dāng)設(shè)備檢測到SDA信號被拉低超過指定時(shí)間時(shí),就在SCL總線上產(chǎn)生9個(gè)時(shí)鐘 脈沖,使I2C從設(shè)備完成讀操作,從死鎖狀態(tài)上恢復(fù)出來。總線恢復(fù)設(shè)備需要有具有編程功能,一般可以用單片機(jī)或CPLD實(shí)現(xiàn)這一功能。
2 參考技術(shù)文檔
萬變不離其宗之I2C總線要點(diǎn)總結(jié)
I2C總線死鎖原因及解決方法文章來源地址http://www.zghlxwxcb.cn/news/detail-488583.html
到了這里,關(guān)于溫故知新(十一)——IIC的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!