I2C protocol 原理及應用

Posted by: 邱小新 at 下午4:14 in
原始碼下載

I²C (Inter-Integrated Circuit) 是內部整合電路的稱呼,是一種串列通訊匯流排,使用多主從架構,由飛利浦公司在 1980 年代為了讓主機板、嵌入式系統或手機用以連接低速週邊裝置而發展。I²C 的正確讀法為 "I-squared-C" ,而 "I-two-C" 則是另一種錯誤但被廣泛使用的讀法,在大陸地區則多以 "I方C" 稱之。截至 2006 年 11 月 1 日為止,使用 I²C 協定不需要為其專利付費,但製造商仍然需要付費以獲得 I²C Slave (從屬裝置位址)。

I²C的參考設計使用一個7位元長度的位址空間但保留了16個位址,所以在一組匯流排最多可和112個節點通訊。常見的I²C匯流排依傳輸速率的不同而有不同的模式:標準模式(100 Kbit/s)、低速模式(10 Kbit/s),但時脈頻率可被允許下降至零,這代表可以暫停通訊。而新一代的I²C匯流排可以和更多的節點(支援10位元長度的位址空間)以更快的速率通訊:快速模式(400 Kbit/s)、高速模式(3.4 Mbit/s)。

I2C 的啟動條件及停止條件

  1. I2C start condition 有二種情況,如上圖所示,虛線表示 read 動作時的第二次 start condition,實線表示 r/w 時的第一次 start condition。
  2. I2C stop condition 只有一種情況,如上圖所示。
void i2c_start(void) { // for second start signal on i2c_read I2C_SDA = HIGH; I2C_SCL = HIGH; i2c_wait(); // send start signal I2C_SDA = LOW; i2c_wait2(); I2C_SCL = LOW; } void i2c_stop(void) { i2c_wait2(); I2C_SDA = LOW; i2c_wait2(); I2C_SCL = HIGH; i2c_wait2(); I2C_SDA = HIGH; }

I2C 的讀寫動作

  1. 當 SCL=HIGH 時,表示 SDA 穩定,可以做讀取動作。
  2. 當 SCL=LOW 時,表示 SDA 混亂,不可以讀取;因為此時可以設定 SDA 的值,也就是做寫入動作。
  3. master 每一次傳送八個 bit,最後 slave 會回傳一個 ack bit,表示接受是否完成。
  4. master 每一次接受八個 bit,最後 master 要傳送一個 ack bit,表示接受已經完成。
  5. 在傳送完第八個 bit 之後,再等待 slave 接受完成後,需將 SDA 設成 HIGH,此時 slave 會將 SDA 拉回 LOW,表示接受動作完成。如果 acknowledge=HIGH,也就是 slave 沒有拉成 LOW 則表示傳送失敗。
bit i2c_write(unsigned char value) { char i=9; bit ack; // upload data while(--i) { i2c_wait2(); I2C_SDA = (value & 0x80) ? HIGH : LOW; i2c_wait2(); // send data I2C_SCL = HIGH; i2c_wait(); value <<= 1; I2C_SCL = LOW; } // get acknowledgement i2c_wait2(); I2C_SDA = HIGH; i2c_wait2(); I2C_SCL = HIGH; i2c_wait2(); ack = I2C_SDA; i2c_wait2(); I2C_SCL = LOW; // return acknowledge return ack; } unsigned char i2c_read(bit acknowledge) { char i=9; unsigned char value=0; // read data while(--i) { value <<= 1; i2c_wait(); I2C_SCL = HIGH; i2c_wait2(); value |= I2C_SDA; i2c_wait2(); I2C_SCL = LOW; } // send acknowledge i2c_wait2(); I2C_SDA = acknowledge; i2c_wait2(); I2C_SCL = HIGH; i2c_wait(); I2C_SCL = LOW; // return data return value; }

標準 I2C 讀寫流程 by Philips

  1. 讀取完最後一個 byte 時,記得要回傳 no acknowledge(SDA=HIGH),表示已經沒有要繼續讀取資料。
  2. 讀取完最後一個 byte 時,回傳 acknowledge(SDA=LOW),再傳送 stop signal,則會造成後續的讀寫動作失敗。(這是在讀取 PCF8593 的經驗)
完整寫入流程

完整讀取流程

複合式讀寫流程

常用 I2C NVRAM 讀寫流程 by Philips PCF8953

  1. 一般 RTC 都有帶一些 NVRAM 或是讀寫 EEPROM,需要先指定讀寫的 register address 才可以。所以在寫時,先寫入 slave address 後,需再寫入 register address,讓 chip 知道你要寫入的起始位址,接下來才能寫入 data。
  2. 由於讀取前也要先寫入 register address,所以一般 NVRAM 讀取動作都是使用標準複合式流程,也就是先寫入 register address,再下一次 start conditon,再做讀取動作。
void i2c_write_byte(unsigned char slave_addr, unsigned char reg_addr, unsigned char value) { char i=10; EA = 0; while (--i) { i2c_start(); if(i2c_write(slave_addr)) continue; if(i2c_write(reg_addr)) continue; if(i2c_write(value)) continue; i2c_stop(); break; } EA = 1; } unsigned char i2c_read_byte(unsigned char slave_addr, unsigned char reg_addr) { char i=10; unsigned char value=0; EA = 0; while (--i) { // send register address i2c_start(); if(i2c_write(slave_addr&0xfe)) continue; if(i2c_write(reg_addr)) continue; // read data i2c_start(); if(i2c_write(slave_addr | 1)) continue; value = i2c_read(1); i2c_stop(); break; } EA = 1; return value; }

12 意見

您好:
因為最近在練習I2C的介面,把您的程式拿來做練習,但在Debug時出現了問題,想請問您是否有呼叫它本身內建的htc和i2c的檔案來做為使用?

裏面有很多 define 我沒有寫出來,比如 HIGH=1, LOW=0,還有 I2C_SCL 及 I2C_SDA 要根據你的板子腳位來定義,有問題歡迎加入我的 msn(jyhshin@msn.com) 來討論。

您好:
我最近也在練習I2C,想請教您的i2c_wait()及i2c_wait2()時間是多長?謝謝!!

在 40MHz 情況下,i2c_wait 使用 10 個 nop 指令,i2c_wait2 使用 5 個 nop 指令。

您好!!
本人最近因要使用mma7455 ic 所以要學習使用i2c,但有個關於地址的問題想請教您,mma7455的地址是:00011101[A7:A0]
而A7 bit是R/W bit,那想請問如果我是要寫入資料而在device address時是[00011101] 還是[10111000]??
i2c規格:
[ST][device address(6:0)][W][register address][ST][device address(6:0)][R][AK][SP]

根據 MMA7455 datasheet 的內容,slave
address ($1D), with the R/W bit set to “0” for a write,所以 slave address for a read is 0x1D,slave address for a write is 0x1C。

那即是寫入是:00011100而讀取是:00011101 對嗎??

您說,
在 40MHz 情況下,i2c_wait 使用 10 個 nop 指令,i2c_wait2 使用 5 個 nop 指令。

所以,如果我使用的是 12MHz , 使用的 nop 就必須越少了嗎?我可以同樣也是使用您提供的工具來計算嗎?

i2c_wait 推導方式請見 http://jyhshin3.blogspot.com/2010/01/i2c-protocol.html,我並沒有提供工具計算喔。

請問如果要學I2C的話 有什麼推薦的書籍嗎??
初學者從頭學的痛苦

請問可以問妳有關bus address、Device address、I2C address的問題嗎?

我想問問 單片機 要是作為從機(slave) 又應該如何編程呢?

張貼留言