邊緣系統VLM視覺理解推論實作工作坊
|
View Categories

I2C 界面解密 — PART 3

閱讀時間: 2 min read

作者:Bird

上一篇文章【Maker電子學】I2C 界面解密 — PART 2,我們聊了 I2C(以下寫作 I2C 界面的底層時序以及它基本的定址方法,接下來我們繼續探討在這個底層的邏輯上要如何傳輸資料、控制不同的週邊晶片。

從點名開始 #

(圖片來源:Bird)

上次我們說過,I2C 的傳輸由 master device 在 bus 上造出 START 狀態開始,緊接著是要接收訊號裝置的 I2C 地址;由於接收訊號的裝置是 slave,因此這個裝置的地址又稱為 slave address。

Slave address 包含了 7 個 bit 的地址以及 1 個 bit 的 R/W bit,這個 R/W bit 代表接下來資料傳輸的方向,而對 master 來說,讀取是 1、寫入是 0。

緊接著 slave address 後,就是一個 byte 一個 byte 的資料。我們來看一下這些資料的基本格式。

基本格式 #

下面是 I2C master 對 slave 寫入一個 byte 資料的格式:

(圖片來源:Bird)

I2C master 用 START 狀態發起傳輸後,接著是 slave address 以及 R/W bite,因爲這時是寫入 slave,因此 R/W bit 是 0,到了第 9 個 bit 時,傳輸方向會換過來,變成由 slave 向 master 傳送 acknowledge bit。

如果 master 在送出第 9 個 SCL 脈波時,SDA 沒有被拉 low,就代表這個 slave address 的點名動作失敗,master 便會用 STOP 狀態停止這一回合的傳輸,不會繼續下面的傳輸動作。這種狀況最常見的原因是 bus 上不存在這個 slave address 的裝置,那既然不存在,就沒有人被點到,自然也就不會有人回答。

如果 bus 上存在對應的 slave 而且它有正確收到 slave address 及 R/W bit,並且可以繼續處理接下來的傳輸,它就會在 master 送出第 9 個 SCL 脈波的週期中,把 SDA 拉到 low,代表「收到、了解、OK、請繼續」。

Master 收到 acknowledge 後,就會繼續切換 SCL,並在每一個 SCL 爲 high 的脈波週期中,依序送出資料的每一個 bit,總共 8 個 bit。

一樣到了第 9 個 bit 時,傳輸方向會換過來。Master 會在 SCL 變成 high 的第 9 個脈波週期中,放掉 SDA 不去驅動它,並傾聽來自 slave 的狀態;如果 slave 在此時有把 SDA 驅動到 low,就代表它有正確地收到了這個 byte 的資料傳輸。

最後,master 送出 STOP 狀態結束這一回合的傳輸,成功寫入 1 個 byte 的資料到 slave。

至於 master 向 slave 讀取資料的基本格式也非常類似:

(圖片來源:Bird)

Master 在送出 slave address 與代表讀取的 R/W bit 後,如果有正確收到來自 slave 的 acknowledge,它就會繼續驅動 SCL,並在每一次 SCL 爲 high 的脈波週期中,從 SDA 讀取 1 個 bit 的資料,直到 8 個 bit 都讀完。

而最後這一個 acknowledge 則是由 master 送往 slave,但它不是用來告訴 slave 說「master 正確收到了」,而是說「我要準備結束傳輸了」,因此在讀取資料時,master 送往 slave 的 acknowledge bit 含義是:

  • ACK=1:master 還會繼續讀取更多的資料
  • ACK=0:master 已經讀完所有的資料了

由於這是個只有 1 個 byte 資料的讀取,因此 ACK 在這種狀況下一定是 0,表示後面不會再繼續讀取更多的資料。

連續讀寫 #

從讀取週期的 acknowledge bit 安排,應該有讀者可以猜到 I2C 可以進行連續的讀寫。沒錯!這個協定當初設計的精神就允許連續的讀寫。

在寫入週期中,只要 master 沒有送出 STOP 狀態,而是持續不斷地切換 SCL 並將資料送出,就會變成一個連續寫入的傳輸:

(圖片來源:Bird)

至於可以連續寫入多少筆資料,則要看 slave 這邊晶片的設計,當寫入太多,超過 slave 可以允許的範圍,它就會用 ACK=1 來喊停,告訴 master 不要再寫了。

而讀取週期的狀況一樣很類似:

(圖片來源:Bird)

在連續讀取時,只要後面還會繼續讀,master 就要送出 ACK=1 的 acknowledge bit 告訴 slave 要準備提供接下來的資料,只有當後面不再讀取而接著 STOP 狀態時,ACK 才會是 0。

如果 master 沒有遵循這個協定送出對應的 acknowledge bit,會發生什麼事呢?在某些狀況下會導致立即的資料錯誤,而在某些狀況下可能會導致下一次讀取時的資料錯誤。

比方說如果 master 在讀完某筆資料後,已經送出了 ACK=0,但確沒有用 STOP 狀態結束傳輸,而是繼續切換 SCL 讀取下一筆資料,這時某些 slave 的晶片可能就會因爲被 master 殺了個措手不及而吐不出正確的資料。

如果 master 在讀完某筆資料後,送出 ACK=1 告訴 slave 它後面還要繼續讀,卻直接用 STOP 狀態結束這一回合,這時 master 並不會拿到任何錯誤的資料(因爲它已經讀完了),但卻可能導致 slave 晶片內部的狀態機異常,造成 master 下一次對 slave 發起傳輸時,因爲這個異常的狀態而讀到錯誤的資料。

以上,我們已經講完了 I2C 規格中關於寫入與讀取的部分。

咦?好像少了點什麼?如果有稍微實作過用 I2C 控制週邊晶片的讀者們,可能會覺得上面說明的協定跟我們平常在用的比起來好像少了些什麼,除了 slave address 之外不是還有什麼暫存器位址的嗎?

事實上在 I2C 剛發展出來的那個年代,一般的數位邏輯 IC 能容納的電晶體數量很有限,並不能處理太複雜的通訊協定邏輯,因此 I2C 協定的設計都是可以用極爲簡單的數位邏輯實作出來的,而那個時候的 I2C 週邊晶片都很簡單,裡面沒有多少設定需要用 I2C 來讀寫,因此用上面說明的協定就可以很簡單地操作。

我們舉個例子來看看。

PCF8574 是一顆可以用 I2C 控制的 I/O 擴展晶片,它可以用 I2C 控制 8 隻 I/O 接腳,可以輸出也可以輸入,可以讀也可以寫。這顆晶片的年紀差不多跟 I2C 協定本身一樣古老,但它現今依然活躍在市場上,而且常常還是很多人學習 I2C 界面時,用來練習的第一顆晶片。

(圖片來源:Bird)

上圖是 NXP 的 PCF8574 規格書中,它的內部結構圖。這顆 I/O 擴展晶片的結構非常簡單,它裡面就只有一個 8-bit 的暫存器,因此當你用 I2C 操作 PCF8574 時,不管是讀還是寫,你的操作對象就一定是這個唯一的暫存器。既然如此,哪來的什麼暫存器位址呢?

I2C 就是誕生在這樣一個純樸的年代,那時候的週邊晶片並沒有爲數衆多的暫存器可供讀寫,因此 I2C 也就沒有定義什麼暫存器位址之類的協定。

直到 EEPROM 出現後,在 I2C 的規格說明文件中,有這麼一段耐人尋味的附註:

NOTES: 

  • Combined formats can be used, for example, to control a serial memory. During the first data byte, the internal memory location has to be written. After the START condition and slave address is repeated, data can be transferred. 
  • All decisions on auto-increment or decrement of previously accessed memory locations etc. are taken by the designer of the device

事實上這一段講的就是後來 I2C 的 EEPROM 發展出來後,利用類似暫存器位址的協定以及連續讀寫的設計,來存取 EEPROM 中爲數衆多的內容,但這些其實並不是 I2C 原始協定規範的一部分,因此上面說 「taken by the designer of the device」,意思就是請設計週邊晶片的人自行發揮,而實際上要怎麼使用,也請使用者自行參閱週邊晶片的說明文件,I2C 的規格沒有管到這一塊。

小結 #

下一回我們將繼續說明,當遇到像 I2C EEPROM 或是其它內容數量衆多的週邊晶片時,I2C 發展了什麼樣的協定來操作。

本系列文章列表連結在此。

(責任編輯:賴佩萱)

Powered by BetterDocs

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *