轉寄網易DP先生關於I2C的博文,便於學習時尋找
最近發現訪問I2C裝置時,主裝置複位可能會引起i2C死結,表現為SCL為高,SDA一直為低,後發現是從裝置拉死i2c匯流排,從裝置斷電之後,SDA變高,上電後通
信正常。後來通過拉低SCL訊號線,SDA就會自動變成高電平,i2c匯流排恢複。
在正常情況下,I2C匯流排協議能夠保證匯流排正常的讀寫操作。但是,當I2C主裝置異常複位時(看門狗動作,板上電源異常導致複位晶片動作,手動按鈕複位
等等)有可能導致I2C匯流排死結產生。下面詳細說明一下匯流排死結產生的原因。
在I2C主裝置進行讀寫操作的過程中.主裝置在開始訊號後控制SCL產生8個時鐘脈衝,然後拉低SCL訊號為低電平,在這個時候,從裝置輸出應答訊號,將SDA
訊號拉為低電平。如果這個時候主裝置異常複位,SCL就會被釋放為高電平。此時,如果從裝置沒有複位,就會繼續I2C的應答,將SDA一直拉為低電平,直到SCL
變為低電平,才會結束應答訊號。而對於I2C主裝置來說.複位後檢測SCL和SDA訊號,如果發現SDA訊號為低電平,則會認為I2C匯流排被佔用,會一直等待SCL和SDA
訊號變為高電平。這樣,I2C主裝置等待從裝置釋放SDA訊號,而同時I2C從裝置又在等待主裝置將SCL訊號拉低以釋放應答訊號,兩者相互等待,I2C匯流排進人一
種死結狀態。同樣,當I2C進行讀操作,I2C從裝置應答後輸出資料,如果在這個時刻I2C主裝置異常複位而此時I2C從裝置輸出的資料位元正好為0,也會導致I2C總
線進入死結狀態。
方法
(1)盡量選用帶複位輸人的I2C從器件。
(2)將所有的從I2C裝置的電源串連在一起,通過MOS管串連到主電源,而MOS管的導通關斷由I2C主裝置來實現。
(3)在I2C從裝置設計看門狗的功能。
(4)在I2C主裝置中增加I2C匯流排恢複程式。
每次I2C主裝置複位後,如果檢測到SDA資料線被拉低,則控制I2C中的SCL時鐘線產生9個時鐘脈衝(針對8位元據的情況,“9個clk可以啟用”的方法來自NXP
的文檔,NXP(Philips)作為I2C匯流排的鼻祖,這樣的說法是可信的),這樣I2C從裝置就可以完成被掛起的讀操作,從死結狀態中恢複過來。
I2C匯流排死結原因及解決方案 - dp - dp: 生活的腳步,進步的點滴...
這種方法有很大的局限性,因為大部分主裝置的I2C模組由內建的硬體電路來實現,軟體並不能夠直接控制SCL訊號類比產生需要時鐘脈衝。 或者,發送
I2C_Stop條件也能讓從裝置釋放匯流排。
如果是GPIO類比I2C匯流排實現,那麼在I2C操作之前,加入I2C匯流排狀態檢測I2C_Probe ,如果匯流排被佔用,則可嘗試恢複匯流排,待匯流排釋放後,再進行操作
。要保證I2C操作最小單元的完整性,不被其他事件(中斷、高優先順序線程,等)打斷。
(5)在I2C匯流排上增加一個額外的匯流排恢複裝置。這個裝置監視I2C匯流排。當裝置檢測到SDA訊號被拉低超過指定時間時,就在SCL匯流排上產生9個時鐘脈衝,使
I2C從裝置完成讀操作,從死結狀態上恢複出來。匯流排恢複裝置需要有具有編程功能,一般可以用單片機或CPLD實現這一功能。
(6)在I2C上串人一個具有死結恢複的I2C緩衝器,如Linear公司的LTC4307是一個雙向的I2C匯流排緩衝器,並且具有I2C匯流排死結恢複的功能。LTC4307匯流排輸
入側串連主裝置,匯流排輸出側串連所有從裝置。當LTC4307檢測到輸出側SDA或SCL訊號被拉低30ms時,就自動斷開I2C匯流排輸入側與輸出側的串連.並且在輸出側
SCL訊號上產生16個時鐘脈衝來釋放匯流排。當匯流排成功恢複後,LTC4307會再次串連輸入輸出側,使匯流排能夠正常工作。