隨著科技的演進, 在單晶片微控制器及 SoC 的領域中, SPI 及 I2C 這二種串列 (序列) 介面變得十分常見. 這二者與主機間通訊用的非同步串列通訊埠 RS-232 (UART) 非常不一樣

  • 二個都是同步傳輸介面, 主要是用於 CPU 和週邊晶片之間.
  • SPI 及 I2C 二者設計的主要目的在於減少 CPU 和週邊晶片之間的接腳數.
  • SPI 一般需要 4 條接線 (至少三條), 而 I2C 則只要二條線, 這和早期常用的並列匯流排動輒十數條接線有著明顯的差異.
  • SPI 的硬體結構簡單而且傳輸速度快, 一般是 5M/10M/20Mbps 或是更快 (可以到 200Mbps), I2C 的傳輸速度則只有 100Kbps/400Kbps/1Mbps(/3.4Mbps/單向5Mbps).
  • SPI 是全雙工, I2C 則是半雙工

本篇介紹的是 I2C 介面

SPI 的部份在這個連結 SPI (Serial Peripheral Interface) 串列 (序列) 週邊介面



I2C Bus 簡介


I2C Bus, 英文全名 Inter-Integrated Circuit Bus, 不過大部份人習慣用省略 bus 的縮寫 I2C 或者是 I2C 來稱呼它 (鮮少人用IIC), 發音是 "I-square-C" 或者 "I-two-C"() (唸成 "I-I-C" 會令人一時想不出你在說的是什麼).

Integrated Circuit 的中文翻譯是積體電路或者也有人直接用英文縮寫 IC. 就像 inter-national 指的是國與國之間相關的東西, 在 Integrated Circuit 前面多一個 inter- 的 "inter-IC bus" 或者 "inter-積體電路 bus" 指的是 IC 或是積體電路之間介接/溝通用的匯流排. 所以個人認為比較恰當的中文譯名應該是積體電路介接匯流排或是直白一點叫 I2C 匯流排, 而不是什麼 "內部集成電路總線" 之類的 (可能是誤認為英文全名為 Internal-Integrated Circuit Bus 吧?).

I2C Bus 是 1982 年由荷蘭飛利浦半導體公司 (Philips Semiconductor) 所開發. 主要是為了讓微控制器或 CPU 以較少的接腳數連接眾多的低速週邊裝置之用 (最主要的市場在電視機及 PC 顯示器的控制器上). 飛利浦公司為 I2C Bus 申請了商標及專利 (1987 年專利成立), 並曾經控告許多半導體公司侵權. 所以後來其他公司 (如: Atmel, Maxim, Cirrus Logic, Linear 等公司) 就將其產品設計成和 I2C Bus 相容 (一般都是只實作部份重要的功能), 並改名為 Two Wire Interface (TWI) 來規避 I2C Bus 專利. 而 CPU 類的晶片為了規避專利則改以半軟體式的方式來實作 I2C Bus 的功能, 有些甚至把 I2C Bus 和 SPI 功能合併, 如: Atmel 的 AVR 系列 ATmega169, ATtiny2313...的 USI port (Universal Serial Interface), 也有連 UART 功能也一起併進來的.

I2C Bus 原專利已於 2004 年到期 (美國早期的「發明專利」專利期為專利獲准日起算 17 年), 之後所有商標和知識產權轉移到 NXP 半導體公司 (2006 年從飛利浦公司分拆出來賣掉了). 自 2006 年 11 月 1 日起, 在晶片上加入 I2C 功能已經不需要再支付專利費, 但製造商如果想取得專屬的 I2C slave 裝置地址則依然需要付費給 NXP 公司. 所以現在各廠家都不再像從前那樣子忌諱用 I2C Bus 的名稱了.

I2C Bus 的規格至今有四次重大更新 (粗體部份):

  • 1982 年: 原始規格, 傳輸速度 100KHz.
  • 1992 年: 1 版, 加入快速模式 (Fast-mode, Fm) 傳輸速度 400KHz, 及 10-bit 定址.
  • 1998 年: 2 版, 加入高速模式 (High-speed mode, Hs-mode) 3.4MHz 及一些節能需求的規範.
  • 2000 年: 2.1 版, 小修正.
  • 2007 年: 3 版, 加入 1MHz 的快速模式 Plus (Fast-mode plus, Fm+) 及設備 ID 機制.
  • 2012 年: 4 版, 加入 5MHz 的超快速模式 (Ultra Fast-mode, UFm)...
  • 2012 年: 5 版, 錯誤訂正
  • 2014 年: 6 版, 訂正二張圖片

和 SPI 比起來, I2C Bus 在參與其他架構準標方面更加的活躍. 常常看到 I2C bus 以自身的協定或者以架構在它之上的 SMBus 為基礎, 再延伸至其他的控制架構/協定上, 例如:

  • 顯示器資料通道 (DDC, Display Data Channel, 一路由 VESA 標準一直帶到 HDMI 標準)
  • 系統管理匯流排 (SMBus, System Management Bus): NoteBook 電池管理, PC 記憶體管理 (提供記憶體容量及 DIMMs 的工作參數等..., 有興趣可以參考 LightSeed 先生這一篇博客: 【我所認知的BIOS】—>SPD)
  • 電源管理匯流排 (PMBus, Power Management Bus)
  • 智慧平台管理介面 (IPMI, Intelligent Platform Management Interface, 屬於 ATCA 架構)
  • ...

備註: 念成 I-two-C 原本無可厚非, 不過大部份都是非英語系國家及非專業人士, 才如此念 (出於不知道平方的英文如何發音). 一般正式的場合裡, 我還是推荐念成 I-square-C. 也謝謝某不知名訪客的提醒.

I2C Bus 架構及介面接腳


I2C Bus 和 SPI 一樣也是主從式架構, 不過它不同於 SPI 的點對點或點對多點結構, 它是以匯流排型式介接, 同時匯流排上允許有多個 master (主設備) 和多個 slave (從設備). 介接方法如下圖所示:

I2C Bus

I2C 晶片介接方法

I2C 的匯流排接線十分簡單, 只有兩條訊號線: 資料線 (SDA, Serial Data Line) 及時脈線 (SCL, Serial Clock Line), 所有 I2C 裝置 (不管是 master 或 slave) 的這二支接腳都是 CMOS 開汲極 (Open Drain) 或者是 TTL 開集極 (Open Colloecor) 的 I/O 接腳(), 並且並接 (Wired-AND) 在這兩條線路上. 接腳的內部開關在導通時為接地的邏輯低準位 (Low), 而不導通時則形同斷線浮接, 不過 I2C Bus 上必需要加入提升電阻 Rp (SDA, SCL 兩條線都需要), 將浮接狀態轉變為邏輯高準位 (High) 狀態. 如下圖:

I2C Open Drain

I2C 晶片 Open Drain 輸出入結構及提升電阻

上圖中除了一對提升電阻 Rp 之外, 還有每個 I2C 設備依現況的需要可選擇加裝一對抗干擾用的電阻 Rs (尤其是當 SDA, SCL 的佈線繞經特殊干擾源時).

應用 I2C 時, 最麻煩的是計算 Rp 的阻值, 及為各個晶片選擇合適的 Rs 阻值. 需要的人麻煩請參考這一篇 I2C Bus 提昇電阻之計算

備註: 由於電氣特性的關係 (CMOS 的運作是靠電壓; TTL 則需要足夠的電流), 二者無法直接混用. 將 CMOS 晶片的開汲極 (Open Drain) 接腳和 TTL 晶片的開集極 (Open Colloecor) 接腳直接接在一起是無法產生 Wire-AND 效果的. 但是這二種技術都各自可以形成 Wire-AND 的效果. 而市面上的 I2C 晶片接腳則 100% 都是 CMOS 開汲極 (Open Drain) 接腳.

Wired-AND


提醒: 因為 Wired-AND 是 I2C 一切運作的基石, 所以這一段請大家務必熟記.

在了解 I2C Bus 協定之前, 大家應該熟記一下 Wired-AND 所代表的意義. 就字面上來看:

  • Wired: 意思是二組 (或者是多組) 接線直接就接在一起.
  • AND: 意思是它具備邏輯閘 AND 的功能.

而 AND 閘的邏輯狀態是全部輸入為 High 時, 輸出為 High. 只要任何一個輸入為 Low 時, 輸出即為 Low. 所以 I2C 晶片的輸出接腳以 Wired-AND 接在一起, 就會有如下的效果:

  • 所有晶片都輸出 High 時, 我們可以在接線上量測到 High.
  • 只要有一個晶片輸出 Low, 我們就會在接線上量測到 Low.

這意味著

  • 晶片可以自由控制 Bus 輸出 Low, 卻不一定能控制 Bus 輸出 High.
  • 必需 Bus 上的其他晶片都輸出 High 時, 我們才能完全掌控 Bus 的輸出.

I2C Bus 協定



I2C 實體層


I2C Bus 協定設計得十分的精巧. 首先我們來看一下實體層的部份, 也就是電路訊號的部份:

  1. SCL 為 Low 時, SDA 可以改變資料. 如下圖標示 ➀ 的位置.
  2. SCL 為 High 時, SDA 必需保持訊號穩定, 不可以改變, 以方便對方讀取(栓鎖)資料. 如下圖標示 ➁ 的位置.
  3. SCL 為 High 時, 如果 SDA 有變動則視為特殊狀況: Start (啟始, SDA 由 High 轉為 Low) 或 Stop (結束, SDA 由 Low 轉為 High). 如下圖二個標示 ➂ 的位置.

上面三條定義剛好把 SCL 和 SDA 二條訊號線會發生的訊號全部都包括了.

I2C Signal

I2C 實體層訊號狀態

Byte 傳輸及 ACK/NACK 機制


I2C Bus 協定在傳輸的內容上也有明確的規定:

  • 除了 Start (啟始) 和 Stop (結束) 二個訊號之外, 所有的訊號傳輸固定 8 bits (1 Byte) 為一組, msb (Most Significant Bit) 先送出.
  • 發送端在每組 (8 bits) 訊號送出後, 需讀取接收端所回應的一個 ACK bit (訊號為 Low) 或者 NACK bit (訊號為 High). (注意: 發送端不一定是 master. 例如: 讀取資料時, 發送端為 slave)

傳輸格式


一般 I2C 晶片常用的傳輸格式有下列二種:

  1. (啟始)-[控制]-[指令]-[資料]-(結束)
  2. (啟始)-[控制0]-[指令]-(r啟始)-[控制1]-[資料]-(結束)
  • 上述格式中, (啟始)(結束)是上上段 "I2C 實體層" 第三點所說的 Start (啟始) 及 Stop (結束) 訊號狀態. [控制], [指令], [資料] 則都是附有 ACK bit 之 1 組或數組 8 bits 訊號.
    • 其實三者本質相同 (除了[資料]可能是由 master 或者 slave 發送之外) 之所分成三個區段只是為了說明方便, 在實作驅動軟體時並沒有必要一定得分清楚三者之間的界限.
  • [控制][指令] 部份一般都是固定長度, 但 [資料] 部份的長度則多半是可變動的.
  • 第一種型式是基本控制格式, 所有晶片都必需支援. 第二種型式則視晶片而定.
  • 第二種型式中的(r啟始)和一般的(啟始)並無不同, 唯一的差別是它原本應該出現在傳輸開頭, 但卻出現在傳輸中, 而這個位置原本預期要出一個(結束).
  • 第二種型式常出現在可以連續寫入/讀取可變組數資料的晶片上 (必需要晶片有支援才行, 例如: Serial EEPROM 就有支援), 第一組 [控制0]和[指令] (一般是一個讀取寫入命令) 先設定 (晶片內部) 暫存器的起始地址; 第二組 [控制1] 才是真正的寫入/讀取命令 (但是省略了 [指令] 部份), 之後緊接著 [資料] 也就是要寫入/讀取的資料.
  • 各種 slave 晶片不必需全部支援這二種傳輸格式. 一般晶片製造廠都是依據實際上的需要來選用及實作傳輸格式, 所以可能只支援其中的一種, 或者二者都支援.
    1. 例一: TI 的 DAC 7571 只支援格式一而且只有一個 (寫入) 命令, 甚至還把 [指令] 及 [資料] 合併在一起使用. (參考: DAC 7571 手冊 Page 16)
    2. 例二: TI 的 TCA 9534 IO Expander, 它的內部有 4 組暫存器. 但是寫入命令只支援格式一, 而且一次只能寫入一個暫存器. 讀取命令則只支援格式二, 可以一次讀出多組暫存器. (參考: TCA 9534 手冊 Page 19~20)
    3. 例三: Serial EEPROM 24LC64, [指令] 部份為二個 Bytes 的 EEPROM 內部記憶體地址, 寫入命令只支援格式一, 一次可以寫入多個暫存器 (最多 32 組). 讀取命令則有二個格式. 一個是格式二, 也是一次可以讀出多組暫存器 (但組數沒有限制), 另一個則是只有格式二的後半段而 ((r啟始)之後). (參考: Microchip 24LC64 手冊) Page 9 & Page 12

傳輸格式說明


  • [控制]:
    • 傳輸內容 (啟始訊號之後) 的第一個 Byte 固定為晶片定址 (bit 7~1) 及讀寫命令 (bit 0).
    • 讀寫命令: 0 為寫入, 1 為讀取.
    • 晶片定址: 定址空間為 7 bits, 共 128 個地址, 但保留了 16 個地址作為系統擴充使用, 所以在一組 I2C 匯流排理論上可以連結多達 112 (128-16) 個節點. (可惜實際的情況不是這樣)
      • 一般 I2C slave 晶片的地址是無法由使用者任意給定的, 而是每一種晶片的製造商經由向 Philips 註冊, 給定一個或者多個特定地址 (註冊是要錢的), 給定多組地址的晶片才可以經由晶片上的地址選擇接腳選定其中一個地址並可以連接多組晶片. 但是, 只給定一個地址的晶片在一組匯流排上就只能使用一組晶片, 想要連接多組這樣的晶片就必需要有多組 I2C 匯流排 (或者在匯流排加上 I2C Multiplexer/Switch 晶片).
      • 注意: 有部份晶片廠商的手冊誤把上述的 I2C 晶片定址讀寫命令結合在一起, 給了二個連續的 (對應的) 8 bits 晶片地址: 一個是寫入用的 (偶數) 地址, 另一個則是讀取用的 (奇數) 地址. 所以請注意一下你用的驅動軟體晶片手冊上對於這一部份的說明是不是一致. 如果用的是 8 bits 地址要除以 2 才是上述的 7 bits 地址.
        8_bits_Address for write = 7_bits_Address x 2
        8_bits_Address for read = 7_bits_Address x 2 + 1
      • 為了擴充晶片的定址能力為 10 bits (因為 7 bit 定址空間用光了?), 當第一個 Byte 的晶片地址為 11110XXb 時 (它佔用了 16 個保留地址中的 4 個), 第二個 Byte 應該依舊解釋為地址, 合併這二個 Bytes 可以再增加一組 10 bits 的定址空間, 格式如下圖.
    I2C 10bit

    I2C 7 bit 及 10 bit 定址格式

  • [指令]: 為一個 Byte 或多個 Bytes, 各家晶片設計不同. 內容或為控制晶片的指令、或為是晶片內部暫存器地址、也可能是二者的組合, 使用者需參考各個晶片的使用手冊, 給予正確的內容方能使晶片正常運作.
  • [資料]:
    • [控制]部份中讀寫命令為寫入時, [資料]發送端為 master, slave 必需作 ACK 回應.
    • [控制]部份中讀寫命令為讀取時, [資料]發送端改為 slave, master 則必需作 ACK 回應.
    • 依據各類晶片不同, 資料內容可以是一個 Byte, 也可以是固定長度的多 Byte 資料, 或者支援變動長度的多 Byte 資料內容.

再談 ACK/NACK


上面提到過 I2C Bus 是一種主從式架構, 所以 I2C Bus 的傳輸都是由 master 端發起, slave 只能就 master 送出的命令作出回應.

  • 以寫入命令來說: [控制], [指令][資料] 三個區段的傳輸訊號主要都是由 master 送出, slave 收到 master 送給它的訊號時 (符合自己實體地址) 只需作 ACK 回應即可.
    • 當 master 讀到 ACK 回應, 即可以繼續傳輸下一個 Byte.
    • 當 master 讀到 NACK 回應, 意思是 slave 無回應, 此時 master 應送出 (結束) 訊號放棄該命令. 至於是否需要重傳, 則視應用而定, 沒有定論.
    • 由於 NACK 是被當作 slave 無回應, 所以寫入命令的最後一組資料 slave 應該都會是以 ACK 來回應.
  • 如果是讀取命令: [控制], [指令] 二個區段的傳輸訊號一樣是由 master 送出, 所以 master/slave 對這二個區段的處理方式和上述寫入命令是一樣的. [資料]段落則不一樣, [資料]段落的發送端換成 slave, 改由 master 作出 ACK/NACK 回應:
    • 當 slave 讀到 master 送出的 ACK 回應, 意即收到資料, slave 可以準備傳輸下一組資料 Byte (除非已經是傳輸格式的最後一組資料 Byte, 此時 master 應該接著送出一個 (結束) 訊號來結束該命令).
    • 當 slave 讀到 NACK 回應, 意思是 master 要求結束傳輸. 此時 master 會繼續送出一個 (結束) 訊號來結束該命令.
    • 另外, 對於傳輸格式的最後一組資料 master 到底應該回應 ACK 還是 NACK? 正式的答案是:請你詳查晶片手冊. 不過可以確定的是: 回應 NACK 一定可以正確結束傳輸, 所以如果你想偷懶, 不想麻煩查手冊, 回應 NACK 就可以了. (我目前用到的晶片全部都是要求以 NACK 來回應最後一組資料.)
  • 發送端讀到 ACK 回應, 一般試視為傳輸成功, 可以繼續傳輸下一個 Byte. 不過要小心的是: 整個傳輸格式中並沒有錯誤檢查欄位, 所以讀到 ACK 回應並不保證傳輸的資料一定正確. 要確保資料傳輸無誤, 只能落實硬體電路的實作 (確實計算提昇電阻 Rp 及 Rs, 並量測二條訊號線的結果是否確實符合規範.)

進階部份: 動作細節



對於初學者來說, 知道上面所說的東西大概就夠用了, 許多比較細節的東西硬體都會幫我們處理掉. 但是如果你想用軟體控制 GPIO 接腳, 寫一個模擬 I2C master 的程式來操作某些 I2C 晶片, 例如: Serial EEPROM 24LS64 之類的, 那就還有一些細節要注意一下.

在繼續讀下去之前, 這裡先要請大家回想一下 Wired-AND 的運作:

  • 所有晶片都輸出 High 時, 我們可以在接線上量測到 High.
  • 只要有一個晶片輸出 Low, 我們就會在接線上量測到 Low.

這意味著對於 SCL 接腳或者 SDA 接腳

  • 晶片可以自由控制 Bus 輸出 Low, 卻不一定能控制 Bus 輸出 High.
  • 必需 Bus 上的其他晶片都輸出 High 時, 我們才能完全掌控 Bus 的輸出.

ACK/NACK Clock Stretching


首先是 ACK/NACK 的 Clock Stretching (延伸/展延) 部份:

  • 首先要注意的是 SCL 上的 High/Low 訊號 (Clock) 主要是 Master 產生的.
  • 發送端送出一組 (8bits) 訊號後 (下圖 ➀), 發送端必需把 SDA 放開 (在 SCL 為 Low 時 SDA 輸出 High), 並由 SDA 讀取接收端所送出的一個 bit 的回應.
  • 接收端要送出 ACK bit 需要依照標準來: 在 SCL 還是 Low 的時候, 把 SDA 拉為 Low, 並且持續到下一個 clock (下圖時序 ➀➁ 之間). (即 SCL 為 Low 時可改變 SDA, SCL 為 High 時不可改變 SDA).
  • 反之, 如果沒有任何接收端作出反應, SDA 就會維持在 High, 發送端就會讀到 High, 此即為 NACK.
  • 之後, 接收端需把 SDA 放開, 而發送端則準備傳送下一組訊號 (下圖 ➁). 如果接收端需要時間來處理收到的訊號 (或者是準備下一組資料), 可以在此時把 SCL 維持在 Low (下圖 ➂), 使 Master 無法改變 SCL 產生 Clock (下圖 ➃). Master 由於監聽到 SCL 並未依自己的輸出而改變為 High 即進入等待狀態. 接收端處理完訊息並且放開 SCL (回復為 High), master 監聽到 SCL 回復為 High 之後才開始 SCL High 週期的計時 (下圖 ➄), 繼續產生 Clock.
  • 3.4Mbps 的高速模式 (Hs-mode)只容許在 ACK/NACK bit 的位置上被 Clock Stretch. 但是標準模式 (Sm), 快速模式 (Fm)快速模式 Plus (Fm+)則每一個 bit 的 SCL 都可以被 Clock Stretch.
I2C ACK/NACK Clock Stretching

I2C ACK/NACK 時序延伸

這裡有一個實戰失敗的案例 (Sorry, 我完全沒有嘲笑的意思) I2C通訊之 Clock Stretch. 該文中提及使用 8051 模擬 I2C Master 卻無法完成 ACK/NACK Clock Stretching. 這其實是有解的:

  • 8051 的 IO 接腳在寫入 1 之後是可以當作 input 用的. 當然前提是模擬 I2C 的接腳是直接用正邏輯, 所以 1 代表輸出為 Hi. (該文也確實提及利用了這個現象).
  • 只要在完成 ACK 回應週期之後, 下一組傳輸開始時 SCL 拉高的後面 (即上圖 ➃), 插入 readPin(SCL) 即可讀回 SCL 訊號.
  • 確認 SCL 是否為我所控之後 (確定是被 8051 拉高了), 再繼續進行原本的流程.

至於為何該文說沒能成功完成, 在此我沒辦法評斷 (因為該文並未將原始碼 POST 上來). 不過依該文所貼的 I2C 協定分析儀上的訊號來看, 我猜很可能是 8051 master 的 read ACK 少做一件事: 沒有在 ACK 完成後 (SDA 拉為 Low, SCL 輸出 High, 再輸出 Low 之後) 把 SDA 訊號放開. 致使 SDA 在 SCL 為 Hi 時上昇, 結果就變成了 Stop 訊號了.

我把原作者所貼的圖片作了一下增強, 並加上一些註解, 如下圖:

I2C Clock Stretch

時序延伸失敗之修正分析圖

  • Master 作 read ACK 回應時 SDA 輸出 Low, 完成後應該在 SCL 還是 low 的時候改為輸出 1, 放開對 SDA 的控制.
  • 而且他這個 bug 應該只會在 slave 回應資料的 msb 為 1 時出現, msb 如果是 0 則仍然正常.

另外如該文中提及的想用硬體觸發中斷來完成, 理論上應該也是 OK 的.


接下來的兩個現象是有關多個 master 如何協調運作, 並不會發生在單一 master 的 I2C 匯流排上.

I2C 匯流排具備了匯流排仲裁能力, 因此 I2C 匯流排上可以有多個 master. 要具備此能力最基本的作法是 master 要能避免干擾別人, 因此所有的 I2C master 會監聽匯流排上的 (啟始) 訊號及 (結束) 訊號. 出現 (啟始) 訊號表示有 master 要使用匯流排, 因此 (啟始) 訊號之後匯流排為忙碌狀態, 必需等到 (結束) 訊號出現, 才會回復為空閒狀態. Master 必需要在匯流排為空閒狀態時才能發出 (啟始) 訊號. 不過這樣只解決了一部份的問題, 二個 master 所發出的 (啟始) 訊號還是有機會撞到一塊. 如果你對所謂"有機會撞到一塊"不是很能理解, 下面我借用一張說明 Ethernet 網路 (使用同軸線) 封包碰撞的 GIF 動畫, 你可能就比較容易想像.

Packet Collision CSMACD

Packet Collision on coaxial cable (CSMA/CD)

真正使 I2C 匯流排具備 multi-master 能力的是下列的二個機制:

  1. 時脈同步
  2. 匯流排仲裁 (Bus Arbitration)

為了能明確描述多個 master 的 SCL 如何協同達成同步, 以下我用 SCL 來稱呼晶片外部所觀測到的 Wired-AND 的 SCL 訊號, 而以 CLK 來稱呼晶片內部所控制的 SCL 訊號. 同樣的我用 SDA 來稱呼晶片外部所觀測到的 Wired-AND 的 SDA 訊號, 而以 DAT 來稱呼晶片內部所控制的 SDA 訊號.

SCL Synchronization


首先是時脈同步:

備註: 感謝網友 Ginny 來信指正. 以下這一段大部份所說的 "所有的 master" 指的是 "所有參與這一回合控制權競爭的 master", 很抱歉造成誤解.)

  • 由於 I2C 訊號是 Wire-AND 在一起, 所有的 master (這個是全部, 而不是只有參與競爭控制權的) 必需要回讀訊號, 以確認外部訊號是被自己控制.
  • 即使監聽匯流排上的 (啟始) 訊號及 (結束) 訊號可以排除 99% 的訊號碰撞的情況. master 依然可能在另一個 master 發出 (啟始) 訊號但卻尚未被該 master 偵測到的情況下發出 (啟始) 訊號. 此時這二個 (啟始) 訊號幾乎是同時發出.
  • 發出 (啟始) 訊號之後 master 會把自己的 CLK 拉至 Low. 由於 Wired-AND 的效應, SCL 訊號會轉變為 Low. (所有參與競爭控制權的) Master 讀到 SCL 訊號變為 Low, 隨即開始計數 SCL 訊號 Low 的時間.
  • SCL 為 Low 的時間計數終了之後 master 會把自己的 CLK 放開. 本來 SCL 應該要在這時回復到 High. 但是由於匯流排上可能有其他的 master 參與競爭控制權, 而它們的計時器可能尚未計數完畢, 因此必需要等到所有參與競爭控制權的 master 的計時器都計數完畢並且把 CLK 放開, 這時 SCL 才會回復到 High.
  • SCL 尚未回復為 High 之前, 已經計數終了的 master 必需進入等候的狀態. 要等到 SCL 回復為 High, 才可以開始計數 SCL 訊號為 High 的時間.
  • SCL 為 High 的時間計數終了之後 master 會把自己的 CLK 拉至 Low, 一但有一個 master 把自己的 CLK 拉至 Low, 即會使 SCL 隨即變為 Low, 進而再次啟動所有參與競爭控制權的 master 轉為啟動計數 SCL 訊號 Low 的時間.
  • 如此遁環下去, 匯流排上的所有參與競爭控制權的 master 也就共同製造出一個同步的 SCL 訊號: Low 的部份由所有參與競爭控制權的 master 中 Low period 最長的一個所控制, High 的部份則由所有參與競爭控制權的 master 中 High period 最短的一個所控制.
  • I2C CLK Sync.

    I2C 多主設備之時序同步

Bus Arbitration


第二個是匯流排仲裁 (Bus Arbitration): 跟隨著這個同步的 SCL 訊號, 參與競爭控制權的各個 master 會各自送出自己要傳輸的對象的定址資料. 而同樣的 SDA 也是 Wired-AND 訊號, 所以現象和 SCL 訊號類似. 不過, master 對 SDA 的檢查要在 SCL 訊號為 High 時才進行, 如果檢查的結果 SDA 和自己的 SDADAT 輸出一致, master 會繼續進行下一個 bit 的輸出. 但如果檢查的結果 SDA 和自己的 SDADAT 輸出不一致, master 必需中止目前的操作, SCLSDA依序把自己的 DATCLK 都放開 (一定要在 CLK 還是 low 時放開 DAT, 次序錯了就會變成 Stop 訊號), 並等候 (結束) 訊號出現後再重新開始參與下一回合的控制權競爭.

這樣的機制會使想和晶片地址較小進行傳輸的 master 具備較高的優先權. 萬一, 各個 master 都同時想和同一顆晶片溝通, 想要執行寫入命令的 master 會比想要執行讀取命令的 master 具備較高的優先權 (因為寫入命令值為 0, 而讀取命令值為 1). 如果整個 [控制] 訊號都比不出優先順序. 接者比 [指令] 訊號, 再不行接者比 [資料], 總會有結果. 即便是最壞最壞的結果:完全一致, 也還是可以運作.

另外, 我記得在 I2C 的手冊上有提到 I2C Bus 不具有優先權. 我認為他想要表達的是 master 晶片並不具備固定的優先權. 因為 (如上一段所述的) 真正的優先權取決於 master 晶片的傳輸對象 (slave 晶片) 的地址.

I2C Bus Arbitration

I2C 多主設備之介面控制權忡裁

小結: I2C Bus 的缺點


由於近代電路的高速及節能需求, 使得原本的 I2C Bus 規範不得不作出一些改變. 不過也因為這些改變使得原本簡單的 I2C 晶片介接變得十分複雜, 例如: 高/低速的 I2C slave 晶片無法混用的問題、不同工作電壓晶片 (5V 晶片, 3.3v 晶片...) 之間介接的問題、還有 I2C 線路易受到干擾...等等問題, 這些都是 I2C Bus 有待改善的缺點. 雖然這些缺點在現實中並非無解, 但總是令硬體設計及測試人員受苦受難. 我們期待未來晶片製造商以及 I2C Bus 規範的修訂更能使這些問題更容易解決.

I2C Bus Netowork

完整的 I2C Bus 介接網路

參考連結


下一篇: I2C 的驅動軟體


可能要忙一陣子才有辦法完工.

arrow
arrow

    MagicJackTing 發表在 痞客邦 留言(51) 人氣()