I2C總線是一種簡單、雙向二線制同步串行總線。它只需要兩根線即SCL(時鍾信號線)和SDA(數據線),就可在連接於總線上的器件之間傳送信息。
I2C采用的是主從式通信方式,通信的過程完全由主設備決定。通訊的起始信號和終止信號都由主設備發送。

起始信號:在SCL時鍾信號在高電平期間,SDA信號產生一個下降沿,起始之后SDA和SCL都為0。
1 void I2C_Start() 2 { 3 I2C_SDA = 1; 4 I2C_Delay10us(); 5 I2C_SCL = 1; 6 I2C_Delay10us(); //建立時間是I2C_SDA保持時間>4.7us 7 8 I2C_SDA = 0; //保持時間是>4us 9 I2C_Delay10us(); 10 I2C_SCL = 0; 11 I2C_Delay10us(); 12 }
終止信號:在SCL時鍾信號在高電平期間,SDA信號產生一個上升沿,終止后保持SDA和SCL都為1,表示總線空閑。
1 void I2C_Stop() 2 { 3 I2C_SDA = 0; 4 I2C_Delay10us(); 5 I2C_SCL = 1; 6 I2C_Delay10us(); //建立時間是I2C_SDA保持時間>4.7us 7 8 I2C_SDA = 1; 9 I2C_Delay10us(); 10 }
I2C總線上可以掛多個從設備,為了區分從設備,每個設備都有自己的地址編碼。當主從通訊時,主設備必須先發送一個從設備的地址。在SCL時鍾信號線處於低電平時,SDA數據線上的地址信息要開始准備了。I2C在傳送地址信息時都是從高位開始傳送。

SCL時鍾信號低電平轉換為高電平再轉換為低電平,一個bit的數據傳送完畢。如果數據傳送成功,從設備將會返回一個應答信號,此時,總線應該要處於空閑狀態,等待應答信號。
1 uchar I2C_SendByte(uchar dat, uchar ack) 2 { 3 uchar a = 0, b = 0;//最大255,一個機器周期1us 最大延時255us 4 5 for(a=0; a<8; a++) 6 { 7 I2C_SDA = dat >> 7; 8 dat = dat << 1; 9 I2C_Delay10us(); 10 I2C_SCL = 1; 11 I2C_Delay10us();//建立時間>4.7us 12 I2C_SCL = 0; 13 I2C_Delay10us();//建立時間>4us 14 } 15 16 I2C_SDA = 1; 17 I2C_Delay10us(); 18 I2C_SCL = 1; 19 I2C_Delay10us(); 20 21 while(I2C_SDA && (ack == 1)) // 等待應答,也就是等待從設備把I2C_SDA拉低 22 { 23 b++; 24 if(b > 200) 25 { 26 I2C_SCL = 0; 27 I2C_Delay10us(); 28 return 0; 29 } 30 } 31 32 I2C_SCL = 0; 33 I2C_Delay10us(); 34 return 1; 35 }
當從設備需要讀取從設備數據時,總線同樣需要處於空閑狀態。當SCL低電平轉換為高電平時,讀取一個bit的數據,SCL再次轉換為低電平時,讀取結束。數據從高位開始讀取。
1 uchar I2C_ReadByte() 2 { 3 uchar a = 0, dat = 0; 4 I2C_SDA = 1; //起始和發送一個字節之后I2C_SCL都是0 5 I2C_Delay10us(); 6 for(a=0; a<8; a++) 7 { 8 I2C_SCL = 1; 9 I2C_Delay10us(); 10 dat <<= 1; 11 dat |= I2C_SDA; 12 I2C_Delay10us(); 13 I2C_SCL = 0; 14 I2C_Delay10us(); 15 } 16 return dat; 17 18 }
