工程師經(jīng)驗分享:采用硬件I2C讀取E2PROM
現(xiàn)象:單片機采用硬件i2c讀取E2PROM,當單片機復(fù)位時,會有概率出現(xiàn)再無法與E2PROM通信,此時SCL為高,SDA一直為低
本文引用地址:http://m.butianyuan.cn/article/201710/368906.htm原因:當單片機正在和E2PROM通信,如果主正好發(fā)生打算發(fā)第9個時鐘,此時SCL為高,而從開始拉低SDA為低做準備(作為ACK信號),等待主SCL變低后,從再釋放SDA為高。如果此時正好單片機復(fù)位,主SCL還沒來得及變低,直接變成高電平,此時從還在等待SCL變低,所以一直拉低SDA;而主由于復(fù)位,發(fā)現(xiàn)SDA一直為低,也在等待從釋放SDA為高。因此主從都進入一個相互等待的死鎖狀態(tài)。
解決方法:最好的方法是采用模擬i2c. 但由于已經(jīng)配置成硬件i2c,程序改為上電或復(fù)位改成發(fā)9個SCL時鐘信號,使從好釋放SDA。
最近發(fā)現(xiàn)單片機(硬件I2C實現(xiàn))讀取E2PROM時候,單片機復(fù)位可能會引起i2C死鎖,表現(xiàn)為SCL為高,SDA一直為低,后發(fā)現(xiàn)是E2PROM從設(shè)備拉死i2c總線,從設(shè)備斷電之后,SDA變高,上電后通信正常。后來通過拉低SCL信號線,SDA就會自動變成高電平,i2c總線恢復(fù)。后查看一篇文章,講的不錯,特摘錄如下:
在正常情況下,I2C總線協(xié)議能夠保證總線正常的讀寫操作。但是,當I2C主設(shè)備異常復(fù)位時(看門狗動作,板上電源異常導致復(fù)位芯片動作,手動按鈕復(fù)位等等)有可能導致I2C總線死鎖產(chǎn)生。下面詳細說明一下總線死鎖產(chǎn)生的原因。
在I2C主設(shè)備進行讀寫操作的過程中。主設(shè)備在開始信號后控制SCL產(chǎn)生8個時鐘脈沖,然后拉低SCL信號為低電平,在這個時候,從設(shè)備輸出應(yīng)答信號,將SDA信號拉為低電平。如果這個時候主設(shè)備異常復(fù)位,SCL就會被釋放為高電平。此時,如果從設(shè)備沒有復(fù)位,就會繼續(xù)I2C的應(yīng)答,將SDA一直拉為低電平,直到SCL變?yōu)榈碗娖?,才會結(jié)束應(yīng)答信號。而對于I2C主設(shè)備來說。復(fù)位后檢測SCL和SDA信號,如果發(fā)現(xiàn)SDA信號為低電平,則會認為I2C總線被占用,會一直等待SCL和SDA信號變?yōu)楦唠娖健_@樣,I2C主設(shè)備等待從設(shè)備釋放SDA信號,而同時I2C從設(shè)備又在等待主設(shè)備將SCL信號拉低以釋放應(yīng)答信號,兩者相互等待,I2C總線進人一種死鎖狀態(tài)。同樣,當I2C進行讀操作,I2C從設(shè)備應(yīng)答后輸出數(shù)據(jù),如果在這個時刻I2C主設(shè)備異常復(fù)位而此時I2C從設(shè)備輸出的數(shù)據(jù)位正好為0,也會導致I2C總線進入死鎖狀態(tài)。
SCL為高,SDA一直為低原因
從:正常時序下:SDA信號是在SCL為低的狀態(tài)下改變,即從應(yīng)答SDA為低電平時,此時SCL應(yīng)為為低電平(即從設(shè)備是先拉低SDA信號,等待主設(shè)備SCL由高變低,“取走”ACK信號后,從再釋放SDA為高)。但如果此時時序被打亂,例如單片機i2c通信時突然復(fù)位,SCL突然變高,則從設(shè)備SDA一直為低,等待SCL變低。
主:SDA被從拉低,故主認為i2c總線占用,一直等待SDA變高這樣主從進入一個相互等待的死鎖過程。
方法:
最好用模擬I2C實現(xiàn),則不會死鎖
?。?)盡量選用帶復(fù)位輸人的I2C從器件。
?。?)將所有的從I2C設(shè)備的電源連接在一起,通過MOS管連接到主電源,而MOS管的導通關(guān)斷由I2C主設(shè)備來實現(xiàn)。
?。?)在I2C從設(shè)備設(shè)計看門狗的功能。
?。?)在I2C主設(shè)備中增加I2C總線恢復(fù)程序。每次I2C主設(shè)備復(fù)位后,如果檢測到SDA數(shù)據(jù)線被拉低,則控制I2C中的SCL時鐘線產(chǎn)生9個時鐘脈沖(針對8位數(shù)據(jù)的情況),這樣I2C從設(shè)備就可以完成被掛起的讀操作,從死鎖狀態(tài)中恢復(fù)過來。這種方法有很大的局限性,因為大部分主設(shè)備的I2C模塊由內(nèi)置的硬件電路來實現(xiàn),軟件并不能夠直接控制SCL信號模擬產(chǎn)生需要時鐘脈沖。
?。?)在I2C總線上增加一個額外的總線恢復(fù)設(shè)備。這個設(shè)備監(jiān)視I2C總線。當設(shè)備檢測到SDA信號被拉低超過指定時間時,就在SCL總線上產(chǎn)生9個時鐘脈沖,使I2C從設(shè)備完成讀操作,從死鎖狀態(tài)上恢復(fù)出來。總線恢復(fù)設(shè)備需要有具有編程功能,一般可以用單片機或CPLD實現(xiàn)這一功能。
?。?)在I2C上串人一個具有死鎖恢復(fù)的I2C緩沖器,如Linear公司的LTC4307如圖2所示:LTC4307是一個雙向的I2C總線緩沖器,并且具有I2C總線死鎖恢復(fù)的功能。LTC4307總線輸人側(cè)連接主設(shè)備,總線輸出側(cè)連接所有從設(shè)備。當LTC4307檢測到輸出側(cè)SDA或SCL信號被拉低30ms時,就自動斷開I2C總線輸人側(cè)與輸出側(cè)的連接。并且在輸出側(cè)SCL信號上產(chǎn)生16個時鐘脈沖來釋放總線。當總線成功恢復(fù)后,LTC4307會再次連接輸人輸出側(cè),使總線能夠正常工作。
評論