> [Reference](https://www.analog.com/en/resources/technical-articles/i2c-primer-what-is-i2c-part-1.html) > 寫很清楚的中文教學: [1](https://makerpro.cc/2020/05/i2c-interface-part1/) [2](https://makerpro.cc/2020/05/i2c-interface-part2/) [3](https://makerpro.cc/2020/06/i2c-interface-part3/) [4](https://makerpro.cc/2020/07/i2c-interface-part-4/) [5](https://makerpro.cc/2020/07/i2c-interface-part5-clock-stretching/) [6](https://makerpro.cc/2020/07/i2c-interface-part6/) [7](https://makerpro.cc/2020/08/i2c-part7-pull-up-resistors/) [8](https://makerpro.cc/2020/08/i2c-interface-part8/) # Addressing * 7-bit * 保留 16 個位址及特殊位址 * `0000000`: 廣播位址。若搭配 R/W bit 為 0 (write),則 bus 上所有 slave 都應該接收並處理這個訊息 (如果它們支援廣播功能) * 最多可和 112 個節點通訊 * 新版 I2C 支援 10-bit * 傳輸 address 時分為兩 byte * 第一個 byte 為 `11110XXY`,`11110` 表示是 10-bit address、`XX` 為 address 的第 9 和第 8 bit (MSb)、`Y` 為 R/W bit,和 7-bit 模式相同 * 第二個 byte 傳送 address 剩下的 8 個 bits # 傳輸速率 * 標準模式 (100 Kb/s) * 低速模式 (10 Kbit/s) * 暫停通訊 (clock rate = 0) * 新版 I2C 支援快速模式 (400 Kb/s)、高速模式 (3.4Mb/s) # Bus ![1-3](https://hackmd.io/_uploads/HkxlvWjkSgg.png) * **Serial (串列)** 、**雙向** 傳輸、Master/Slave 架構 (支援 multi-Master,但同一時間只能有一個 Master 控制 bus;支援 multi-Slave) * SDA (Serial Data Line): 傳輸 data 及 address signal * SCL (Serial Clock Line): 傳輸 clock signal * 所有 device (包含 Master 及 Slaves) 的 SCL 及 SDA I/O 線皆需為 **open-drain (開集極)**,表示他們只能主動輸出 0,當所有裝置都輸出 float (高阻抗) 時才會讓 bus 拉高為 1 (故稱為 **wired AND**) * VDD 常用 5V 或 3.3V * [Rp (pull-up resistor (上拉電阻)) 需根據 bus 總電容及 rising time 來選擇](https://makerpro.cc/2020/08/i2c-part7-pull-up-resistors/) ## 詳細的 I2C I/O port 電路示意圖 ![](https://makerpro.cc/wp-content/uploads/2020/05/1-5.png) * SDA 及 SCL 皆為 quasi-bidirectional (同時為輸出及輸入) 接腳,透過一個緩衝器來輸入 (listen) 目前 bus 上的狀態 ## Timing Diagram ![36689](https://hackmd.io/_uploads/HyPiSvA4xl.png) :::warning 1. **I2C 並不是邊緣觸發,而是在某個準位的時間內都可以做事** 2. **SDA 線上的資料只能在 SCL 為 0 時改變**。當 SCL 是 1 時,SDA 必須 **穩定** (否則可能會被解釋成 Start/Stop Condition)。故 Receiver 需要在 SCL 為 1 時 read 資料 * ![1-14](https://hackmd.io/_uploads/Sy6Tcoyree.png) ::: 1. 未傳輸時,Master 將 SCL 及 SDA 維持在 1 2. **Start Condition**: SCL 為 1、Master 將 SDA 由 1 變 0 3. 完成 Start Condition 後,Master 先在 SCL 為 0 時傳送 address 的 **MSb**,Slave 在下一個 SCL 為 1 的時間內讀取。並依次傳送至 LSb * 每個 Slave 皆會 listen 這 7 個 bit,只有 address 相符的 slave 才會繼續 listen 之後的東西 4. 傳送完 7-bit address 後,Master 傳送 1-bit 表示 **Read** (1, Master read Slave) 或 **Write** (0, Master write Slave) operation :::warning datasheet 上寫 8-bit I2C address,就表示已包含了此 R/W bit,若要做 R/W 要自己改變這個 address 的 LSb ::: 6. 之後 Slave 會傳送 1-bit **ACK** (0 為成功、1 可能表示沒有符合此 address 的 slave 造成無應答或其他情況) * 這時此 Slave 會 assume 之後的所有 transaction 都是與自己有關,直到 Stop Condition 發生 * 此時 slave 也會依照 Read/Write bit 決定自己是 transmitter 或 receiver 7. 之後 transmitter 依次傳送要傳送的多個 byte 資料 (**MSb** 依次傳送至 LSb、並且大部分是 MSB 依次傳送至 LSB (I2C 沒有嚴格規定 byte order))。每傳送完一個 byte,receiver 傳送 1-bit **ACK** (0 為成功、如果 Master 是 receiver,則此 ACK 傳 1 表示告訴 Slave 此次傳輸到此為止) 8. **Stop Condition**: Master 將 SCL 維持在 1、Master 將 SDA 由 0 變 1 9. **Repeated Start**: 可以不用每次都一定要先用 Stop Condition 來 terminate,可以直接產生下一個 Start Condition。如此可避免 Master 釋放 bus 的控制權,可形成 atomic operation :::info ++Remark++ 1. NACK 的常見情況 * 無此 address 的裝置 * Slave 忙碌中: Slave 成功接收到位址,但在後續的資料傳輸中,它可能因為內部正在處理其他任務 (例如: 正在將前一個 byte 寫入 EEPROM) 而無法再接收新的資料 * 資料錯誤: Slave 接收到的資料或命令是它無法理解或處理的 2. 10-bit receive mode 較特別,addressing mode 需要送 **3** 個 byte,第一個 byte 的 R/W bit 要是 **W** 而不是 R (因為如果是 R 的話,資料流方向就會立刻變成 slave 驅動 SDA)。並且第二個 byte 送完時需要送 **Repeated Start** ![image](https://hackmd.io/_uploads/HJS-1xZwWe.png) ::: # Clock Stretching 使用在當較低速的 Slave 忙不過來時,通知 Master 暫停傳送的方法 示意圖: ![3-1-768x322](https://hackmd.io/_uploads/SyZPZhyHle.jpg) * **Master 每送出 SCL 的一個 clock 時,都會同時 listen SCL 的狀態** * Slave 在接收完某個 bit 之後若要進行 clock stretching,則 **把 SCL 設為 0** * Master 隨後在 SCL 為 0 時繼續發送下一個 SDA data。當 Master 因為 I2C wired-AND 特性導致無法讓 SCL 設為 1 時表示發生 clock stretching :::info ++Remark++ 1. clock stretching 也會引發一些潛在問題,例如有裝置長時間把 SCL 設為 0 而癱瘓整個 bus 2. 由於 clock stretching 需要接腳同時進行輸入與輸出,要用軟體模擬 I2C 的話需要有 quasi-bidirectional port。在早期 8051 有 quasi-bidirectional port 可以使用,但現今 ARM Cortex-M MCU 已少見這種 port,故須用兩個接腳模擬 SCL 的行為 3. slave 只能在 SCL 為 0 時 hold SCL (i.e. 只能 **延長** SCL 0 的時間,而不能強行將 SCL 從 1 變為 0) ::: # Multi-Master 當有 multi-Master 時需要考慮 **clock synchronization (時脈同步)** 及 **bus arbitration (bus 仲裁)** ## Clock Synchronization 用來讓不同 clock 週期的 Master 變為一樣 支援 clock synchronization 的 I2C Master 會有兩個 **clock period counter**,分別計算預定的 SCL high 與 SCL low 時間 * 當 Master 認為 SCL low period 應該結束 (即計數器達到門檻) 時,會偵測實際 SCL 線是否已回到 high。若 SCL 實際仍為 low,表示有其他更慢的 Master 尚未釋放 SCL,Master 必須等待 * 等到 SCL 回到 high,所有 Master 累加 high counter 的值直到 SCL 再次回到 low 故每個裝置的 counter 最後都會變成一樣的值: * low counter = 把 SCL 拉低最久的 Master 決定 * high counter = 把 SCL 維持在 high 最短的 Master 決定 從下一個 SCL 脈波開始,所有的 Master 就會用這一組 low/high 時間來同步產生接下來的 clock ## Bus Arbitration ![1595688065858](https://hackmd.io/_uploads/H1WG2VMSlg.jpg) 若 Master 驅動 SDA 為 high,但實際從 SDA 線上讀到的是 low,表示有其他 Master 正在驅動 low,且優先權較高,因此該 Master 仲裁失敗,需停止傳輸並等待下一次 bus 空閒 (SCL 及 SDA 皆為 1 時) # [Level Shifting](https://makerpro.cc/2020/08/i2c-interface-part8/) 當兩裝置的工作電壓不同時需有 level shifting 電路