1、基本概念
主機 初始化發送,產生時鐘信號和終止發送的器件
從機 被主機尋址的器件
發送器 發送數據到總線的器件
接收器 從總線接收數據的器件
多主機 同時有多於一個主機嘗試控制總線 但不破壞報文
仲裁 是一個在有多個主機同時嘗試控制總線,但只允許其中一個控制總線並使報文不被破壞的過程
同步 兩個或多個器件同步時鐘信號的過程
2、硬件結構
每一個I2C總線器件內部的SDA、SCL引腳電路結構都是一樣的,引腳的輸出驅動與輸入緩衝連在一起。其中輸出爲漏極開路的場效應管、輸入緩衝爲一隻高輸入阻抗的同相器。這種電路具有兩個特點:
(1)由於 SDA、SCL 爲漏極開路結構,藉助於外部的上拉電阻實現了信號的“線與”邏輯;
(2)引腳在輸出信號的同時還將引腳上的電平進行檢測,檢測是否與剛纔輸出一致。爲 “時鐘同步”和“總線仲裁”提供硬件基礎。
3、時鐘同步
如果從機希望主機降低傳送速度可以通過將SCL主動拉低延長其低電平時間的方法來通知主機,當主機在準備下一次傳送發現SCL的電平被拉低時就進行等待,直至從機完成操作並釋放SCL線的控制控制權。這樣以來,主機實際上受到從機的時鐘同步控制。可見SCL線上的低電平是由時鐘低電平最長的器件決定;高電平的時間由高電平時間最短的器件決定。這就是時鐘同步,它解決了I2C總線的速度同步問題。
4、主機發送數據流程
(1)主機在檢測到總線爲“空閒狀態”(即 SDA、SCL 線均爲高電平)時,發送一個啓動信號“S”,開始一次通信的開始
(2)主機接着發送一個命令字節。該字節由 7 位的外圍器件地址和 1 位讀寫控制位 R/W組成(此時 R/W=0)
(3)相對應的從機收到命令字節後向主機回饋應答信號 ACK(ACK=0)
(4)主機收到從機的應答信號後開始發送第一個字節的數據
(5)從機收到數據後返回一個應答信號 ACK
(6)主機收到應答信號後再發送下一個數據字節
(7)當主機發送最後一個數據字節並收到從機的 ACK 後,通過向從機發送一個停止信號P結束本次通信並釋放總線。從機收到P信號後也退出與主機之間的通信
注意:①主機通過發送地址碼與對應的從機建立了通信關係,而掛接在總線上的其它從機雖然同時也收到了地址碼,但因爲與其自身的地址不相符合,因此提前退出與主機的通信;②主機的一次發送通信,其發送的數據數量不受限制。主機是通過 P 信號通知發送的結束,從機收到 P 信號後退出本次通信;③主機的每一次發送後都是通過從機的 ACK 信號瞭解從機的接收狀況,如果應答錯誤則重發。
5、主機接收數據流程
(1)主機發送啓動信號後,接着發送命令字節(其中 R/W=1)
(2)對應的從機收到地址字節後,返回一個應答信號並向主機發送數據
(3)主機收到數據後向從機反饋一個應答信號
(4)從機收到應答信號後再向主機發送下一個數據
(5)當主機完成接收數據後,向從機發送一個“非應答信號(ACK=1)”,從機收到ASK=1 的非應答信號後便停止發送
(6)主機發送非應答信號後,再發送一個停止信號,釋放總線結束通信
注意:主機所接收數據的數量是由主機自身決定,當發送“非應答信號/A”時從機便結束傳送並釋放總線(非應答信號的兩個作用:前一個數據接收成功,停止從機的再次發送)。
6、總線死鎖原因分析
I2C總線寫操作過程中,主機在產生啓動信號後控制SCL產生8個時鐘脈衝,然後拉低SCL信號爲低電平,在這個時候,從機輸出應答信號,將SDA信號拉爲低電平。如果這個時候主機異常復位,SCL就會被釋放爲高電平。此時,如果從機沒有復位,就會繼續I2C的應答,將SDA一直拉爲低電平,直到SCL變爲低電平,纔會結束應答信號。而對於主機來說,復位後檢測SCL和SDA信號,如果發現SDA信號爲低電平,則會認爲I2C總線被佔用,會一直等待SCL和SDA信號變爲高電平。這樣,主機等待從機釋放SDA信號,而同時從機又在等待主機將SCL信號拉低以釋放應答信號,兩者相互等待,I2C總線進人一種死鎖狀態。同樣,當I2C進行讀操作時,從機應答後輸出數據,如果在這個時刻主機異常復位而此時從機輸出的數據位正好爲0,也會導致I2C總線進入死鎖狀態。
解決方案通常有如下幾種:
(1)將從機的電源設計爲可控,當發生總線死鎖的時將從機復位
(2)可以在從機的程序中加入監測功能,如果總線長時間被拉低則釋放對總線的控制
(3)在主機中增加I2C總線恢復程序。每次主機復位後,如果檢測到SDA被拉低,則控制SCL產生<=9個時鐘脈衝(針對8位數據的情況),每發送一個時鐘脈衝就檢測SDA是否被釋放,如果SDA已經被釋放就再模擬產生一個停止信號,這樣從機就可以完成被掛起的讀寫操作,從死鎖狀態中恢復過來。這種方法有一定的侷限性,因爲大部分主機的I2C模塊由內置的硬件電路來實現,軟件並不能夠直接控制SCL信號模擬產生需要時鐘脈衝
7、處理器的I2C模塊會在如下所述的情況產生中斷信號
RX_UNDER 當處理器通過IC_DATA_CMD寄存器讀取接收緩衝器爲空時置位
RX_OVER 當接收緩衝器被填滿,而且還有數據從外設發送過來時被置位;緩衝器被填滿後接收的數據將會丟失
RX_FULL 當接收緩衝器達到或者超過IC_RX_TL寄存器中規定的閾值時被置位;當數據低於閾值時標誌位將被自動清除
TX_OVER 當發送緩衝器被填滿,而且處理器試圖發送另外的命令寫IC_DATA_CMD寄存器時被置位
TX_EMPTY 當發送緩衝器等於或者低於IC_TX_TL寄存器中規定的閾值時被置位;當數據高於閾值時標誌位將被自動清除
RD_REQ 當i2c模塊作爲從機時並且另外的主機試圖從本模塊讀取數據時被置位
TX_ABRT 當i2c模塊無法完成處理器下達的命令時被置位,有如下幾種原因:
* 發送地址字節後沒有從機應答
* 地址識別成功後主機發送的數據從機沒有應答
* 當i2c模塊只能作爲從機時試圖發送主機命令
* 當模塊的RESTART功能被關閉,而處理試圖完成的功能必須要RESTART功能開啓才能完成
* 高速模塊主機代碼被應答
* START BYTE被應答
* 模塊仲裁失敗
無論標誌位什麼時候被置位,發送緩衝器和接收緩衝器的內容都會被刷新
RX_DONE 當i2c模塊作爲從機發送數據時,如果主機沒有應答則置位;這種情況發生在i2c模塊發送最後一個字節數據時,表明傳輸結束
ACTIVITY 表明i2c模塊正在活動,這個標誌位將會一直保持直到用以下4種方式清除:
* 關閉i2c
* 讀取IC_CLR_ACTIVITY寄存器
* 讀取IC_CLR_INTR寄存器
* 系統重啓
即使i2c模塊是空閒的,這個標誌仍然需要被置位直到被清除,因爲這表明i2c總線上有數據正在傳輸
STOP_DET 表明i2c總線上產生了STOP信號,無論模塊作爲主機還是從機
START_DET 表明i2c總線上產生了START信號,無論模塊作爲主機還是從機