# I2C(Inter-Integrated Circuit) ###### tags: `protocols ` ## I2C 介紹 * I2C協定使用2條線,一條是資料線(SDA),另一條是時鐘線(SCL),可以連接多個裝置,每個裝置有一個唯一的7 bit或10 bit addres。 * I2C分為Master and slave. * Master: 主動發送 * Slave : 被動發送(需要機器訪問才會回答) ### I2C Master and slave * master transmit — master node is sending data to a slave * master receive — master node is receiving data from a slave * slave transmit — slave node is sending data to the master * slave receive — slave node is receiving data from the master ### I2C Speed 1. 標準模式 (Standard-mode), 速率可高達 100 kbit/s 2. 快速模式 (Fast-mode), 速率可高達 400 kbit/s 3. 快速模式PLUS (Fast-mode Plus), 速率可高達 1 Mbit/s 4. 高速模式 (High-speed mode), 速率可高達 3.4 Mbit/s. ## I2C bus 優缺點 * 優點: 1. 節省引腳:I2C使用2條線路進行通信,比其他協議需要的引腳更少。 2. 能夠多主機:I2C允許多個Chip共享同一個I2C總線。 3. 支援多種速率:I2C支援多種傳輸速率,包括標準模式(100 kbps)、快速模式(400 kbps)和高速模式(3.4 Mbps)。 4. 傳輸距離長:I2C可以在數米的距離內傳輸數據。 5. 通信安全:I2C通信具有校驗和錯誤檢測機制,確保了通信的可靠性和安全性。 6. 最多64組,且address不衝突。 - 假設 7 bit address ,總共有 128 個 I2C address 可用,十六進製表示法的範圍從 0x00 到 0x7F。因此,總線上的每種類型的設備(例如,傳感器、微控制器等)都有 64 個 I2C address可用。 * 缺點: 1. 傳輸速度較慢:I2C的傳輸速度比其他協議如SPI和CAN慢。 2. I2C設備多容易有address衝突:I2C最多只能有64組address,且不同的設備可能使用相同的address,可能會產生address衝突,可透過GPIO 或 I2C Switch IC去解決。 3. 抗雜訊較弱:I2C傳輸數據的電壓範圍較小,受到電磁干擾(EMI)和其他噪聲或抗雜訊的影響,可能導致通信失敗。 ## I2C Protocol ![](https://i.imgur.com/D5751LB.png) * SDA : 資料線,所以的資料交換都是在SDA上完成 * SCL : 時鐘線,由Master輸出用 * I²C的傳輸包括了四個部分: * 最開頭的Start信號,接下來會接上設備的I²C地址與傳送的資料,最後會接上一個Stop信號。 * 每一個封包8-bit(I2C是以1-byte為單位傳送data) 的資料傳輸結束後,會跟著一個 acknowledge bit or non-acknowledge bit(第9個bit)。這個 acknowledge bit or non-acknowledge bit 固定由接收方產生,有兩種用法: ### ACK 1. 當 master傳送方(Transmitter)、slave接收方(Receiver),也就是說這個傳輸是 master 寫入資料到 slave 時,這個 acknowledge bit 是用來讓 slave 告訴 master「收到!了解!正確!」 2. 當 master 是接收方(Receiver)、slave (Transmitter)是傳送方,也就是說這個傳輸是 master 從 slave 讀取資料時,這個 acknowledge bit 是用來讓 master 告訴 slave「我還要接著讀,請繼續準備下一筆資料」或者是「夠了,我讀完了」。 (1) master正常收到data的話SDA會在第9個bit拉LOW也就是回應ACK,SCL則會拉HING - slave正常收到data的話SDA會在第9個bit拉LOW也就是回應ACK,SCL則會拉HING (2) 如果接收方正常收到data的話,會在第9個bit將SDA拉low,也就是回應ACK。 (3) 如果接收方有任何狀況,或是 bus 上面根本就沒有那個 address 的 slave 裝置,到了第 9 個 SCL 週期時,當傳送方釋放SDA後,就沒有人去驅動 SDA,這時 SDA 就會因為上拉電阻(Rp)的關係維持在 high,如此一來,傳送方就知道出問題了,不會繼續接下來的傳輸,而要進行錯誤處理,這種情況稱之為「non-acknowledge」,或簡稱為「NACK」。 ![image](https://hackmd.io/_uploads/HJgRo-cKC.png) ### 產生NACK的五大原因: 1. 在multiple data read傳輸中,當Master要告知Slave停止傳輸,則會在最後一個data byte收下後,改發NACK以告訴Slave裝置data讀取已結束。 2. 沒有裝置去回應ACK (根本沒有接任何裝置或是發出的address不屬於bus上任一個裝置所有)。 3. 接收的裝置因為某種原因無暇進行指令的接收。 4. 傳輸過程中,接收裝置收到了他無法理解的資料。 5. 傳輸過程中,接收裝置的資料Buffer滿了,未處理前,再也收不下來。 6. 傳輸過程中,雜訊太多容易產生NACK。 ![image](https://hackmd.io/_uploads/BkMzyM9FR.png) ## 用其他家IC來解釋I2C Protocol R/W ### NTC7904D ![image](https://hackmd.io/_uploads/B1IgJRut0.png) ### LTC3350 * 屬於ADI IC,他們家IC在讀寫的時候要注意大端序(Big Endian)和小端序(Little Endian) * 如果ARM base(NXP)在讀寫讀回來是Big Endian需要把他轉成Little Endian ![image](https://hackmd.io/_uploads/HkdDWROYA.png) ### ADE7880 * 屬於ADI IC,他們家IC在讀寫的時候要注意大端序(Big Endian)和小端序(Little Endian) * 如果ARM base(STM32)在讀寫讀回來是Big Endian需要把他轉成Little Endian. * 這顆IC 做完init之後會有個上鎖,這個上鎖是假的會影響到ITHD and VTHD and HZ讀出來的數值. 1. Read ![image](https://hackmd.io/_uploads/HywsYa_tC.png) 2. Write ![image](https://hackmd.io/_uploads/ry5TXC_t0.png) ![image](https://hackmd.io/_uploads/HyszSCOKC.png) ## I2C 硬體 ![image](https://hackmd.io/_uploads/Sk-6xsOFC.png) 1. I2C BUS 上所有的裝置都是透過 open-drain 或 open-collector 的方式來驅動 SCL 或 SDA。一般 push-pull 的數位邏輯輸出電路會有 high/low 兩顆電晶體,各自負責把輸出拉到 high 或 low 的工作,但 open-drain 或 open-collector 的輸出則只有 low-side 一顆電晶體。 - MCU可以透過一開始寫預設值的時候來改變要open-drain or push-pull. ![image](https://hackmd.io/_uploads/BkWuwpdYR.png) 2. I2C 的實體界面只有兩根訊號,分別稱之爲 SCL(serial clock)與 SDA(serial data),而由於 I2C 是一個 bus,在這個 bus 上所有的裝置都得透過這兩個訊號線相連,也就是說 I2C 只需要兩根訊號線,就可以讓很多(多達上百個)裝置彼此之間互相通訊,如何讓多個裝置溝通而不打架呢?後續會再詳細說明。 * 上圖是一個典型的 I2C bus 電路,bus 上的所有裝置都透過 SCL/SDA 這兩根線相連。I2C 允許 bus 上可以有多個 master、多個 slave 存在,只要彼此的 address 不衝突、裝置數量沒有超過 bus 的電氣特性上限就沒有問題。 * 在上圖這個電路中,有兩個電阻,分別將 SCL 和 SDA 拉到 VCC。這兩顆電阻稱之爲 I2C bus 的「上拉電阻」(pull-up resistors, Rp),看起來好像沒什麼複雜的地方,但它們卻是 I2C bus 能正常運作的關鍵,而Rp的電阻值也需要工程師的精心設計或者可查看datasheet 建議或者公式換算。 ## 遇到I2CBUS被拉住的解決辦法 * 基本上三種方式可以解決I2CBUS被拉住的情況 * 方案一:軟體強制恢復 (Clock Generator/Bit-Banging) 將 I2C 引腳切換為 GPIO 模式,手動送出 9 個 Clock 脈衝,強迫 Slave 釋放總線,隨後再發送一個 STOP 訊號。目的是讓卡住的 Slave 釋放 SDA 線。 * 原理:I2C 一幀資料為 8 bits + 1 bit ACK = 9 bits。最糟的情況是 Slave 正在傳輸 0 或處於 ACK 階段時 Master 當機,導致 SDA 被 Slave 永久拉低。手動補足 9 個 Clock 能強迫 Slave 走完該幀通訊並釋放 SDA。 * 最糟的情況是 Slave 正好在回傳 0 (ACK),且剛好 Master 當機。 * 在 9 個 Clock 之後,務必發送一個 STOP 訊號(SCL 為 High 時,SDA 由 Low 變 High),確保所有 Slave 回到待命狀態。。 * 方案二:硬體重置 (Master/Slave Reset) 執行 Master Reset 或透過 Reset 引腳重新啟動 Slave 裝置。如果硬體電路有拉 Reset Pin 到 MCU,這是最乾淨利落的方法。 * 方案三:Timeout跟Detection機制 * 異常偵測機制 (Detection Mechanism) 建立偵測機制,當發現 SDA 或 SCL 持續處於 Low 狀態超過特定時間(Timeout)時,自動觸發上述的恢復程序。 * 超時偵測與自動恢復 (Timeout Detection): 在程式碼中加入監控機制,若 SDA/SCL 處於非預期的低電位過久,即判定為 Bus 鎖死並自動執行復位程序。 * 優化上拉電阻: * 如果上拉電阻過大,導致SDA上升沿太慢,請減小電阻值以增強驅動能力(例如從 10K歐姆 換成 4.7K歐姆 或2.2K歐姆 ## 參考文獻 * [I2C的工作原理與技術分析](https://rexpighj123.pixnet.net/blog/post/219960237)