公告版位

目前 '手機版' 有點問題, 只能麻煩大家暫時用 '電腦版' 看.

從小害怕寫作文, 文筆不佳到現在, 還請各位讀者大大:
1. 發現有錯誤, 請留言告知. (或者你 '覺得' 不對也行)
2. 用字措辭不當, 請留言告知.
3. 有看沒有懂? 幫到忙也好, 幫倒忙也罷, 總之留個言吧.

隨著科技的演進, 在單晶片微控制器及 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 架構)
  • ...

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


在了解 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 之類的, 那就還有一些細節要注意一下.

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 的驅動軟體


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

文章標籤
創作者介紹

傑克! 真是太神奇了!

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


留言列表 (15)

發表留言
  • 訪客
  • 這篇讓我看懂I2C協定在幹嘛,還自製了SSD1306的驅動程式(VHDL),真的超棒~
  • 多謝誇獎.
    如果有什麼沒有說明清楚的, 也麻煩幫忙提醒或補充.

    MagicJackTing 於 2016/08/16 19:22 回覆

  • 數位菜逼八
  • 你好,拜讀你的文章後真的了解很多,其中有點好奇一般data送出跟接收都是edge觸發,為什麼您畫的圖轉態的時間都不是edge,這樣怎麼latch到data?以第三張圖來說,bit7是在SCL為falling還是rising去latch data?
    可能問題有點初學者,還請不要偷笑我~
  • 你說的沒錯, 大部份電路設計上都會利用 scl edge 來觸發 data 的送和收.

    但是 I2C 的規範卻只是說 SCL 為 low 時 SDA 可以改變, SCL 為 high 時 SDA 必需保持不變. 所以如果要說用 edge 來觸發的話, 那應該是用 SCL 的 rising/falling edge 都可以用來 latch data. 因為 SCL 為 low 時, SDA 改變, 之後 SCL 要變 High 再變為 Low, SDA 才可以再變化 (因為 SCL 為 high 時 SDA 必需保持不變).

    其實不知你對 100K bps 和 400K bps 這二個傳輸速度的感覺如何? 個人一看到這二個規範上的數字時, 就覺得這是小顆 MCU 用軟體就可以實作出來的速度 (沒那麼神啦, 那時剛好需要決定 MCU 定時掃描輸入的頻率, 正在估算 MCU 執行中斷所需的時間), 所以如果你是以硬體偵測接腳變化, 以軟體實作協定的角度去看 I2C 規範, 就會比較容易了解為什麼規範這麼寫, 然後實作出來的訊號會長成這個樣子了.

    MagicJackTing 於 2016/09/21 15:39 回覆

  • Ginny
  • 您好
    拜讀您的文章後獲益良多
    想請教在匯流排仲裁時,SCL會透過上述方法同步(時脈同步),而同步這SCL的,就是同時發出Start condition 的兩個master嗎?
    另外想請教,在進行同步SCL後,是兩個Master 一起輸出Address 之後,若SDA上的質與輸出不同,即喪失權限,此時SDA需在clock為High時做檢查,這裡的clock應該是同步後的SCL? 而非自己的Clock嗎?
    謝謝您分享好文章
  • Q1. Yes. 匯流排的仲裁指的是: 發生訊號碰撞時, 如何決定誰才是 '當下' 這個時間點的 master.
    Q2. Yes. 如文中所提 "master 對 SDA 的檢查要在 SCL 訊號為 High 時才進行", 因為 slave 是在 SCL 為 High 時才讀取資料, 所以此時才能判定到底誰輸誰贏.
    倒是一但確認自己沒有主控權而中止操作, "把 SCL 和 SDA 都放開": 其實是不需要對自己的 CLK 和 DAT 接腳作什麼動作 (因為你會輸二個訊號一定都是 High), 所以只要改變自己內部的狀態機即可.

    MagicJackTing 於 2016/12/26 21:39 回覆

  • chung
  • 您好:
    拜讀您的文章後獲益良多!!
    為什麼I2C傳200多筆資料後會花生錯誤?是否需要有需所謂的I2C補償電路來更正傳送錯問的發生?I2C補償電路又該如何做呢?
    thanks!!
  • 1. 很抱歉,我並沒有聽過I2C補償電路,所以也不知道要如何做
    2. 你說可以傳200多筆資料,可見你的硬體應該沒有什麼大問題,軟體也99%是正確的
    3. 由於你提供的資訊並不十分充足,我只能猜你有一個什麼重要狀況沒有處理正確,才會有這種現象。可能是中斷的處理,可能是多工的 Buffer,也可能 I2C 驅動程式本身(例如: Clock Stretching 沒處理正確) 或是其他。我想你的 I2C 啟始程式 (initialization) 可能也少了一段解鎖死的用的程序,這段程序原本是要再寫一篇討論 I2C 趨動的文章中提出,但是很抱歉一直無法抽空完成它。有了這段程序至少在 I2C Bus 鎖死的時候 master 可以自行解開,而不用斷電重開機 (有些應用的狀況是連斷電重開機也解不開)。I2C Bus 鎖死是它最嚴重的問題,也只能靠解鎖死程序才能在不斷電的狀況下自行回復。SMBus 及 PMBus 就有提供這方面的規範,但 I2C 則完全沒有提到。
    4. 如果方便的話麻煩你把狀況再描述清楚:用了什麼 IC,作了什麼樣的動作,卡在哪裡...?不方便公開的話也可以直接寄 email 給我 (jacktingHOTMAIL .com) 我很樂意撥出一㸃時間幫忙看一下

    MagicJackTing 於 2016/12/30 22:43 回覆

  • Ginny
  • 您好
    想請教一下
    I2C 的ACK 訊號是不是非必要?
    透過I2C改版的SMBUS對於ACK訊號似乎比較要求一定要有?
  • I2C 的 ACK 訊號是必要的, 文章中 '傳輸格式' 有提及: '[控制], [指令], [資料] 則都是附有 ACK bit 之 1 組或數組 8 bits 訊號.'
    缺少了 ACK 訊號, 後續的傳輸是無法繼續進行的. 意思是一但遇到 NACK, 後面就只能接 STOP, 結束這一次的傳輸 (不論你後面還有沒有資料要繼續讀出或寫入)

    最早 SMBUS 是建立在 I2C Bus 為基礎的 '軟體' 傳輸協定, 再附加上一些硬體規格上的限制好讓硬體相容性更容易達成. (之所以會如此是因為 IC 都是現成的, 不需另外訂製)
    你可從下面的網址下載到它最原始的規範, 才短短的 17 頁, 研讀一下你會發現它只是借用 I2C Bus 來傳資料 http://smbus.org/specs/smb10.pdf

    MagicJackTing 於 2017/06/15 14:40 回覆

  • Ginny
  • 您好:
    謝謝您詳細回答。
    想另外請教,I2C有支援multi-master的功能,請問master的身分是固定的嗎?
    還是可以轉換?
    如果不能交換?請問Master與master之間如何溝通?
    謝謝您!
  • 我們一般用的 I2C 晶片都是 I2C slave, 是不能切換為 I2C master 的.
    但是 MCU 則可以實作是 master 或 slave 功能, 一般我們都只會實作 master. 當然你也可以實作 slave. 或二者併存.

    實作 slave 的第一件是需要決定的是 device id. 如果你想要完成的是一個只有 MCU 用 I2C 串在一起的網路, 那就不需要遵守飛利浦公司所訂定的規則, 就你自己決定吧, 只要每一個 MCU 都有一個唯一的 ID 就可以. 但如果不是只有 MCU, 你就要小心挑幾個沒有和 slave 晶片衝突的 ID 了.

    再下來就是 master 什麼時切換為 slave 了? 這個完全決定於你的傳輸協定設計及軟體實作能力了. 一般常用機制有 token ring, token pass, CSMACD, CSMACA, CDMA...
    不過你可以完全忽略他們, 只利用我在文章中描述的 I2C multi-master 的特性: SCL 同步, 和 ID 值小溝通的 master 優先權高.

    再來是:
    1. 沒事時, MCU 必需是 slave. 只有有事想和其他 MCU 溝通時才切換為 master.
    2. 因同時傳輸必需放棄的 master 不能只是停止傳輸, 必需判斷對方是要和你溝通嗎? 如果是, 立即換成 slave mode 並作出對方要你完成的任務.

    MagicJackTing 於 2017/01/06 01:09 回覆

  • Ginny
  • 您好
    謝謝您總是詳細的回覆
    不知道能否寫信與您討論I2C與SMBus相關問題?
  • OK, 只要有空我會盡可能回覆.

    MagicJackTing 於 2017/02/02 23:10 回覆

  • 黃坤照
  • 您好!
    感謝此文章提供寶貴知識及應用.首先我不是學程式的並不專業.想請教一些問題
    我有一電路用i2c接收20cm線長度的感知元件訊號再計算送出去pwm給6v馬達.老是實驗桌上都正常,但是一移到發動的車輛上就會偶發性當機(有wdt啟動),已經排除是電源干擾,只要離車子遠一點即可,一旦上車就會發生.請問如何解決?謝謝.
    有作屏蔽,雙隔離線及電路濾波了
  • 很抱歉, 你雖說很努力的描述狀況, 不過卻還是資訊不足, 我無法提供確實的解決方法.
    我只能先給你幾個方向:
    1. 請先將 "馬達用電" 獨立出來.
    2. 控制電路請遠離馬達及可能的磁迴路. (必要時'屏蔽'控制電路... 你說的屏蔽是這個嗎?)
    3. 請你們家的老師傅(或類比電路高手)確實把 '接地' 處理好.

    你所說的 '有作屏蔽,雙隔離線及電路濾波了' 我擔心你是否'確實作對'了?

    另外, 你對自己的程式沒信心嗎? 啟動 WatchDog 其實是下下策.

    MagicJackTing 於 2017/02/14 21:02 回覆

  • Heero
  • 看到您的介紹受益良多!!!請問版主是否有機會介紹MIPI呢?
  • 可是, 我也才剛在看規範而已 (而且是抽空看).
    要到能寫出東西來, 還不知要多少時間耶?

    MagicJackTing 於 2017/03/16 13:24 回覆

  • Heero
  • 謝謝版主的回覆,沒關係,我期待您的介紹^_^
  • OK, 我盡量不偷懶.

    MagicJackTing 於 2017/03/17 02:43 回覆

  • 感謝!!
  • 太感謝你的介紹了
    讓我了解open drain
    想請問UART SPI LPC 等等之類的其他bus
    是用push pull 還是open drain呢 我困惑好久
    網路上也比較少其他bus的資料
  • 在此要先聲明我不是電子相關科系的, 電子學方面的東西都是夠用而已, 所以可能有些見解不是完全正確. 如果有說錯的地方 敬請指正.

    以我的了解:
    1. push pull, open drain 主要和邏輯IC的扇出級設計相關. 一般是某類邏輯IC族群為了要和自己或其他族群介接時才有特別的設計 (例如: TTL 裡有 74HCT 族群可以專門和 CMOS 晶片介接).
    另外就是傳輸用的 IC 也會特別講究這個 (因為關係到阻抗匹配: 關係到不同品牌的 IC, 不同牌子的線材... 接在一起之後能否正常運作)

    2. UART 指的是 '非同步傳輸' 時用的晶片, 輸出入都是邏輯準位的訊號 (TTL/COMS). 他對外會另外接 '收發器' (Transceiver). 收發器才會分 RS-232, 423, 422, 485... 等不同標準, 才會用不同電氣特性的介接電路.
    所以你要查的是 RS-232, 423, 422, 485... 不同規範的電氣特性有什麼特別規定.

    3. SPI 和 LPC 基本上也都是講 '邏輯準位' 的訊號, 並沒有特別需要注意的. 除非你是 '硬體工程師' 需要負責線路的 layout, 或者你是 'IC 設計工程師' 需要設計和這些晶片的 IO port.

    4. 參考資料
    SPI 可以請參考 http://magicjackting.pixnet.net/blog/post/164725144

    LPC 規範請參考 http://www.intel.com/design/chipsets/industry/25128901.pdf
    page 9 有說明哪些接腳是 OD
    (Sorry, intel 把資源鎖了, 要簽 CNDA 才能下載.) 替代 URL:
    https://web.archive.org/web/20170214213125/http://www.intel.com/design/chipsets/industry/25128901.pdf

    Sorry 可能有點不太了解你的癥結點在哪裡? 如果還不明白, 麻煩再把問題點陳述清楚一些.

    MagicJackTing 於 2017/06/06 13:12 回覆

  • MagicJackTing
  • 我再仔細想了一下你的問題 '... 等等之類的其他 bus 是用 push pull 還是 open drain 呢?'
    你的意思是: 不明白為何有些規範的接腳用的是 push pull, 但有一些接腳卻要用 OD 嗎 ?
  • 如果是的這個意思的話, 回覆如下:
    請你回想一下 push pull 和 OD 這二者之間的重大差異:
    A. push pull 一般是用在 '一個輸出' 推動 '多個輸入', 最大的限制是同時只能有一個輸出.
    B. OD 可以把 '多個輸出' 直接接在一起, 變成 wire-and 效果. (所以可省掉一個 AND gate, 而且是一顆輸入接腳數可以變動的 AND gate).

    所以在傳輸電路的設計上:
    1. 只要訊號特性是:一頭是輸出, 另一頭是輸入的 (或者是一個輸出對多個輸入的) 那就用 push pull 電路即可. 而這個一般是 '點對點' 傳輸.
    2. 如果訊號特性是會 (只要是有機會發生) 多個輸出撞在一起的, 例如 bus 的接法: bus 上可能有多個 bus master 會競爭 bus 的主控權時, 多半會利用這樣的 wire-and 的特性來作為 bus master 的仲裁機制. (不一定要用 wire-and 電路, 但多半是有類似特性) 這樣的設計不是最好的, 但卻是成本最低的.

    以 I2C 為例: 它的實體接法就是 bus, 所以 90% 以上的機率會要用到有 OD 特性的接腳. 加上規範上說 SCL 接腳會發生 clock stretch: 慢速的 slave 可以把 SCL hold 在低電位來通知 master. 這就發生了多個輸出同時搶一支接腳訊號, 所以 SCL 必需是使用 OD 特性的接腳.

    相對的 SPI 則完美的避開使用 OD 特性的接腳, 只用 push pull. 優點是可以高速 (20MHz 對 SPI 只是小菜), 缺點是接腳多.

    不知這樣舉例, 你了解了嗎?

    至於 UART 的收發器由 RS-232 發展到 RS-422/423 再到 RS-485 則是見證了電路設計人對 '阻抗匹配' 的理解歷史. 也見證了 '電介面' 短距離傳輸如何向極限速度推進的發展歷史: 由 '不平衡' 介面電路進步到 '平衡' (差動) 介面電路.

    MagicJackTing 於 2017/04/27 10:57 回覆

  • mybeauty
  • 寫的非常的清楚,造福廣大網友。謝謝您!
  • 嗯, 不客氣.
    :D

    MagicJackTing 於 2017/05/16 13:23 回覆

  • 感謝!!
  • 非常感謝你詳細的回答,我獲益良多
    我現在的理解是

    open drain 架構的IC 好處就像I2C bus一樣,能夠不使用chip select就能達成一對多傳輸,缺點是速度慢。

    push pull 架構的IC 好處是速度快,缺點則是若要達成一對多傳輸則需要多的pin來做chip select。

    您的講解真的讓我學到很多

    最後希望若您有時間能講解LPC bus
    我一直被其中的Frame signal 搞得好亂 ~~~~

    提供一些資訊,從實際量測的波型來看目前我看到屬於open drain特徵的波型只有I2C , SVID , 其他都是bus 都是 push pull ~~~~
  • sorry, 我看錯了, 以為你在說的 SVID 是 '接腳名稱'. 原來還有 SVID 這種 VR 晶片專用的介面.

    講解 LPC ? ㄜ...需要用到 LPC 的人應該不多了吧?

    而且最近工作很忙. 又積了十幾篇文章都寫到一半, 有些是細部的資料不好找的, 有些是要多讀書的, 有些是要抽空作實驗的...

    所以 LPC 的優先順序可能會比較低, 不要抱太大的希望會很快寫出來. 真的很 sorry.

    MagicJackTing 於 2017/06/07 23:23 回覆

  • lamuness40
  • 您好,最近剛好在了解I2C,讀到您的文章真的受益良多。

    另外想請問幾個問題:

    1.一般I2C晶片的address會只有固定值嗎?如果只有固定值,那Master要如何區分衝突的address?

    2.我有注意到一些裝置一個slave能有多個address,有點想不到哪些應用或需求會使用多個slave address?
  • 1. slave address 是要花錢買的 (向 NXP 註冊), 所以沒錢可以只買一個, 有錢就多買幾個. 有多個 address 晶片要用 CS 接腳來將 address 固定.

    2. 晶片只註冊了一個 address, 但是你需要用到多個晶片時, (如果你沒有第二個 I2C port 可用的話) 只能多加一顆 I2C Multiplexer 或 I2C Switch 晶片. 它多半是有一個 master port, 以及二個 (或以上) slave ports. master 可以下指令給 multiplexer 要切換到哪一個 slave port.
    slave port 選好了, 再對原先的晶片下指令.

    3. 有很多種 IC 會需要多顆啊.
    例如 SEEPROM 單一顆容量不足, 就多加一顆. 還有 AD/DA 晶片也是.
    不過 AD/DA 一般會選用 SPI 介面的. 因為一般 SPI 介面的 AD/DA 晶片可以多顆晶片同步運作: 同時換輸出值, 或同步開始轉換輸入值.
    一般 '數控工具機' 會有這種要求. 試想如果你停在 (0,0) 要以 45度移動到 (100,100) 是不是要 x 軸馬達和 y 軸馬達一起動啊! (先動 x 或先動 y 你都無法一次到位, 其中一軸會有徧移量)

    這些在段落 '傳輸格式說明'-->'[控制]'-->'晶片定址' 裡都有說明, 請細讀.

    MagicJackTing 於 2017/06/08 00:00 回覆

找更多相關文章與討論

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼