1. 程式人生 > >I2C通訊 讀寫資料過程

I2C通訊 讀寫資料過程

在通訊之初,主從機必須根據自己的要求約定好通訊規則:command的定義和位置、address的位數和位置。

以讀寫從機暫存器資料為例:

假設從機暫存器地址為8位、從機暫存器也位8位(被讀取資料為8位);

約定讀command為0x01,寫command位0x02;

約定主機發起通訊後,第一個slave address位元組收到ack後,緊跟的一個位元組為command,再下面一個位元組為address。

1. 讀暫存器資料步驟:

    1.1 主機先發起一次通訊,將讀command(0x01)和需要讀取的暫存器地址address寫入從機;(主機發出寫操作)

    1.2 從機firmware的處理:

          1.2.1 將command和address分別提取出來;

          1.2.2 判斷command的含義(本例中,是讀指令還是寫指令);

          1.2.3 根據收到的的address,將對應暫存器的的資料放入從機I2C輸出buffer;(這個步驟可以使用指標)

    1.3 主機再次發起一次通訊,讀取從機的資料;(主機發出讀操作)



2. 寫操作步驟:

    2.1 主機發起通訊,按約定依次寫入command、要寫入的從機暫存器地址address和要寫入的資料data;

    2.2 從機firmware要做的處理:

          2.2.1 分別提取command、address和data;

          2.2.2 根據command做出判斷(本例中則判斷是寫入還是讀取);

          2.2.3 將data寫入與接收到的address對應的暫存器。(這個步驟可以使用指標)。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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訊號模擬產生需要時鐘脈衝