3.23. I2C 基礎

I2C(Inter-Integrated Circuit,唸作「I-squared-C」或「I-two-C」)是一種雙線串列匯流排,專為同一塊板上晶片間的短距離連結而設計。它在優先順序上介於 SPI 與 UART 之間:比 SPI 慢,但更節省接腳,而且具有定址能力(同樣兩條線上可掛多個裝置),不像 SPI 每個裝置都需要一條專屬的 CS 線。

I2C 是低速率感測器的首選匯流排——加速度計、溫度感測器、濕度感測器、磁力計、即時時鐘、EEPROM——這類應用中,節省接腳與降低匯流排複雜度比原始吞吐量更重要。

3.23.1. 兩條線、皆為開汲極

一條 I2C 匯流排只有兩個訊號:

  • SCL(串列時脈)。(多數時候)由控制器驅動。

  • SDA(串列資料)。由當下正在說話的裝置驅動——位址與外送資料期間是控制器,讀取與 ACK 位元期間是周邊裝置。

兩條線皆為開汲極:匯流排上的每個裝置都能把線拉低到接地,但永遠不會主動把線驅動為高。匯流排上的兩個上拉電阻(通常為接往供電軌的 2.2 10 )會在沒有人拉低時把線拉高。線及邏輯(wired-OR)行為由此而生——任何把線拉低的裝置即勝出,而高電位狀態僅代表「沒有人在說話」。

MCU 在其 SCL 與 SDA 接腳上的內部上拉通常不足以單獨充當匯流排上拉;正常情況下需要在匯流排上加裝外部電阻。許多感測器轉接板已內含這些電阻;在加裝更多之前請先查閱資料手冊。

3.23.2. 交易(transaction)

每一次 I2C 交易都遵循相同的形態:

SCL 與 SDA 波形。SDA 在 SCL 為高時下降 (START),接著 SCL 在 SDA 上送出位元組——一個帶有讀/寫位元 與 ACK 的 7 位元位址位元組、 然後是一個暫存器位元組與一個 ACK、再來是一個資料位元組 與一個 NACK,最後 SDA 在 SCL 為高時上升(STOP)。

一次 I2C 交易:START、7 位元位址 + R/W、ACK、暫存器、ACK、資料、NACK、STOP。

整個交換逐位元展開:

  • START。 控制器在 SCL 仍為高時把 SDA 拉低。這個不尋常的邊緣告訴匯流排上的每個裝置:一次交易即將開始。

  • 位址 + R/W。 控制器送出一個 7 位元周邊位址,後接一個讀/寫位元(0 表示寫入、1 表示讀取)。

  • ACK / NACK。 每個位元組之後,接收方會在一個時脈期間驅動 SDA 以表示 ACK(低)或 NACK(高)。對位址位元組而言,周邊裝置若辨識出自己的位址便會回應 ACK;若沒有裝置回應 ACK,控制器看到 NACK,便知道該位址不在匯流排上。

  • 資料位元組。 每一個之後都跟著來自接收方的一個 ACK。寫入時,周邊裝置對每個位元組回應 ACK;讀取時,控制器對每個它還想要的位元組回應 ACK,並對最後一個位元組回應 NACK,以告知周邊裝置停止。

  • STOP。 控制器在 SCL 為高時釋放 SDA 使其為高,結束這次交易。

重複起始(repeated start)是指在中途不發出 STOP 的情況下發出第二個 START——控制器在不放棄匯流排的前提下,於同一個周邊裝置上切換方向(先寫位址、再讀位址)。

3.23.3. 定址

7 位元位址空間涵蓋 0x080x77;兩端的數值保留作特殊用途。每個裝置的位址由晶片設計者設定;許多元件允許在板級層面變更低位元中的幾個位元(藉由把某接腳接高或接低),如此一來兩顆相同的感測器便能掛在同一條匯流排上。

若兩個裝置共用同一位址,就無法在不互相干擾的情況下與其中之一通訊,因此配對元件前請先查閱資料手冊。i2c.scan()(於 以程式碼操作 I2C 中說明)會遍歷位址空間並回報哪些位址有回應,這是查明匯流排上有什麼的標準做法。

3.23.4. 優點與缺點

這條匯流排的優缺點界定了它的定位:

  • 兩支接腳掛許多裝置。 單一組 SCL/SDA 即可承載十幾個感測器。SPI 則需要每個裝置額外一支 CS 接腳。

  • 標準速度。 100 kHz(「標準模式」)與 400 kHz(「快速模式」)幾乎涵蓋每一種感測器。1 MHz 可達,但開始對匯流排電容與上拉電阻的取值提出更高要求。

  • 相對於 SPI 較慢。 任何傳輸超過每秒數百千位元的應用都會改用 SPI。

  • 位址衝突。 同一條匯流排上有兩個位址相同的裝置,是這個協定無法迴避的硬體錯誤。