I2C總線是Philips公司推出的一種二線制同步串行總線,它由時鐘線(SCL)和數(shù)據(jù)線(SDA)兩根傳輸線組成。I2C總線具有接口線少、控制簡單、器件封裝形式小、兼容性好、通信速率較高等優(yōu)點,使它成為很多器件的標準接口和標準功能模塊。它成為近年來微電子通信控制領域廣泛采用的一種總線標準。I2C總線雖然簡單,但在實際使用過程中出現(xiàn)的問題還不少,其中最為常見的問題就是I2C總線死鎖。當出現(xiàn)I2C總線死鎖時,總線上的設備無法正常工作,整個總線陷入癱瘓狀態(tài),這對于一些要求高可靠性和高安全性的自動控制系統(tǒng)而言,是無法接受的。
I2C總線的標準數(shù)據(jù)幀由主設備發(fā)出的開始信號(START)作為起始標志,再是包含讀/寫操作標志位的從地址信號,緊跟其后的是與從地址匹配的從設備的應答信號(ACK),接著是由從設備(讀操作)或主設備(寫操作)發(fā)出的數(shù)據(jù)信號,緊跟每一個字節(jié)數(shù)據(jù)信號(以8位數(shù)據(jù)為例)之后是接收設備的應答信號(ACK)。當數(shù)據(jù)信號傳輸完畢后,最后是主設備發(fā)出的結束信號(STOP)作為數(shù)據(jù)幀的結束標志。
I2C總線的特性可概括為:
(1)接入I2C總線的器件,SCL和SDA都必須是雙向開漏結構的,通過總線上的上拉電阻拉到邏輯高電平,這樣的結構可以實現(xiàn)線與(&)功能;
(2)一般情況下,I2C總線的SDA只有在SCL為低電平的時候才能改變,SCL為高電平的時候SDA需要保持;
(3)例外的,由主機發(fā)出的起始信號START(SCL為高時,SDA由高變低)和停止信號STOP(SCL為高時,SDA由低變高);
(4)由于I2C總線的線與結構特性,只要總線上任何一個器件拉低了SDA或SCL,其他器件都無法拉高它們。如果有器件不釋放總線,則整個總線上的通訊都會被暫停。
根據(jù)I2C總線的特性,SDA或SCL被拉低后,I2C總線將出現(xiàn)死鎖的情況。對于SCL,一般標準I2C從設備不會影響到SCL,只有是MCU作為I2C從設備時出現(xiàn)程序錯誤,或在多主的情況下出現(xiàn)控制沖突,而導致SCL被拉低,但一般可以通過程序優(yōu)化或添加防沖突機制加以避免。因此在此重點討論單主控制下SDA被拉低的情況。
主設備主動拉低SDA不會導致I2C總線死鎖,因為可以通過復位I2C來重新進行I2C總線的控制。而I2C從設備一般不具備復位引腳,如果其將SDA拉低,將導致死鎖的發(fā)生,即使主設備復位都無法解除。
根據(jù)I2C總線的工作原理,以下兩種情況會出現(xiàn)從設備拉低SD A:
(1)主設備向從設備寫數(shù)據(jù)或地址時,從設備如果發(fā)出ACK應答,則會在第9個CLK的期間拉低SDA;
(2)主設備讀數(shù)據(jù)的時候,從設備會在數(shù)據(jù)位為0時對應的CL K期間拉低SDA。
根據(jù)I2C的特性,SCL為高的時候,SDA的電平應保持,而等到SCL變低后,SDA電平才能發(fā)生改變。如果在SCL的前半個周期變?yōu)楦唠娖胶?,主設備因某些原因不再拉低SCL,則從設備將持續(xù)拉低S DA,I2C總線將一直處于被占用狀態(tài)。
在主設備進行寫數(shù)據(jù)或地址操作,當從設備發(fā)出ACK應答信號拉低SDA時,如果主設備突然復位,將導致時鐘信號不完整,進而引起從設備持續(xù)拉低SDA。復位后的主設備也就無法給出啟動信號或停止信號來使從設備釋放對總線的占用,這樣就出現(xiàn)了I2C總線死鎖。
在主設備進行讀數(shù)據(jù)操作,當從設備發(fā)出的數(shù)據(jù)位為0而拉低S DA時,如果主設備突然復位,類似的,因從設備收不到完整的時鐘信號,導致持續(xù)拉低SDA,進而出現(xiàn)I2C總線死鎖的情況。
在主設備進行讀數(shù)據(jù)操作過程中,當接收完最后一個數(shù)據(jù)時,正常情況應該給出NACK信號告知從設備不再讀取新的數(shù)據(jù)。但如果主設備錯誤地設置了的讀取數(shù)據(jù)長度寄存器值,或因外部干擾等因素導致錯誤地發(fā)出了ACK信號。于是從設備將繼續(xù)發(fā)送新數(shù)據(jù),若數(shù)據(jù)的第一位恰巧為0,從設備將對應地拉低SDA。而對于主設備而言,其已完成所有數(shù)據(jù)的接收,準備給出停止信號STOP,但由于從設備拉低了SDA,導致主設備無法發(fā)出停止信號,這樣主從設備相互等待,陷入死鎖的境地。
解決I2C總線死鎖問題的方法較多,大致有以下幾種:
(1)選用自帶防止I2C總線死鎖的從設備;
(2)選用帶復位輸入的I2C從設備;
(3)從設備的電源由主設備控制;
(4)I2C總線上增加一個額外的總線恢復設備;
(5)在I2C總線上串入一個具有死鎖恢復功能的I2C緩沖器;
(6)在I2C主設備中增加死鎖自恢復程序。
在這些解決方法中,“增加死鎖自恢復程序”相對比較方便和實用,獲得了較廣泛的現(xiàn)場應用。但使用這個方法的前提條件是,主設備的SDA和SCL可以配置為普通的GPIO功能。
死鎖自恢復程序的工作原理為:用GPIO在SCL上模擬時鐘信號,同時檢測SDA的狀態(tài)有沒有被釋放(變?yōu)楦唠娖剑坏z測到SDA被釋放,重新將SDA和SCL配置為I2C功能,發(fā)送停止信號ST OP,告知從設備前次被中斷的通信結束了,至此I2C總線死鎖被解除恢復。
分析了I2C總線產(chǎn)生死鎖的原因和出現(xiàn)死鎖的不同情況,著重描述了“死鎖自恢復程序”的實現(xiàn)原理。設計者可根據(jù)上述分析的原因,采取對應的措施加以避免,同時可采用“死鎖自恢復方法”有效解決I2C總線死鎖帶來的影響,使系統(tǒng)的可靠性和安全性得到提高。