1 IIC總線的連接
IIC傳輸數據的時候只用其實只需要兩根線,一根是“SCL”為時鍾線,一根是“SDA”為數據線
我們來看一下器件是怎么連接在IIC總線上的!
可以看到,SDA和SCL都接了上拉電阻,在總線空閑的時候,SDA和SCL都應該為高電平,當總線上的任何一個器件輸出低電平,那總線都將變為低電平。
數據有效性
我們記住只要記住一條:IIC總線在進行數據傳輸時,當SCL線為高,SDA線必須保持穩定,也就是說,在當拉高SCL線的時候,SDA線不能改變其電平,只有當SCL為低電平的時候才允許SDA線進行跳變,需要注意的是這個規定只是在進行數據傳輸的時候起作用,其他時候比如生成起始信號的時候可以不理睬。
2 IIC的電平信號
在使用IIC總線的時候我們主要有以下幾個信號。
一,起始信號當我們使用IIC總線的時候第一個發送的就是這個信號
IIC協議規定當SCL為高電平的時候,SDA由高到低跳變,為起始信號
下面來看一下代碼
//起始信號 void IIC_Start(void) { SDA = 1; //先將SDA和SCL都拉高為起始信號做准備 SCL = 1; Delay5us(); //延時穩定 SDA = 0; //拉低SDA線,又高到低跳變,起始 Delay5us(); //延時穩定 SCL = 0; //拉低SCL線,鉗住IIC總線 }
二 停止信號
IIC協議規定當SCL為高電平的時候,SDA由低到高跳變,為停止信號,和起始信號正好相反
下面來看一下代碼
//停止 void IIC_Stop(void) { SCL = 0; //先將SDA和SCL都拉低為起始信號做准備 SDA = 0; Delay2us(); //延時穩定 SCL = 1; //拉高SCL等待SDA上升沿 Delay2us(); //延時穩定 SDA = 1; //拉高SDA Delay5us(); SCL = 0; //拉低SCL,鉗住總線 }
三 應答信號
IIC協議規定當SCL為高電平的時候,SDA為低,為起始信號,注意這里是需要在SCL的高電平到來之前SDA線需先將低電平准備好,並在SCL為高期間穩定
下面來看代碼
//答應 void IIC_Ack(void) { SCL = 0; //先將SDA和SCL都拉低為起始信號做准備 SDA = 0; Delay2us(); //延時穩定 SCL = 1; //將SCL拉高 Delay5us(); //在此延時階段,SDA一直為低 SCL = 0; //拉低SCL,鉗住總線 }
四 非應答信號
這個就和答應信號相反,SCL為高期間,SDA也為高並保持穩定就可以了!
下面看代碼
//不答應 void IIC_NAck(void) { SCL = 0; //將SCL拉低為高電平做准備 SDA = 1; //將SDA先拉高 Delay2us(); SCL = 1; //拉高SCL Delay5us(); SCL = 0; //鉗住總線 }
五 等待答應信號
發送器每發送完一個字節(8個脈沖),在第9個脈沖間釋放總線,接收器返回一個ACK信號,協議規定,低電平為有效應答,高電平為無效應答。
看以下代碼
//等待答應 bit IIC_Wait_Ack(void) { uint8_t temp = 0; //定義臨時計數變量 SDA = 1; //先拉高SDA Delay5us(); //延時穩定 SCL = 1; //拉高SCL准備讀取SDA線,SDA和SCL同時為高,釋放總線控制權 Delay5us(); while(SDA) //當SDA拉低變為低電平的時候表示有效答應,調出循環 { temp++; if(temp>250) //當循環250次后SDA還沒有拉低,則表示沒有答應信號(不准確的延時) { IIC_Stop(); return 1; //沒有答應返回1 } } SCL = 0; return 0; //有答應,返回0 }
六 發送1個字節
//發動1個字節 void IIC_Send_Byte(uint8_t dat) { uint8_t t; //臨時計數變量 SCL = 0; //拉低SCL,鉗住總線,准備發送數據 for(t=0;t<8;t++) //循環8次,一次發送1位 { SDA = (dat&0x80)>>7; //去低四位,然后左移七位,先發高位 dat=dat<<1; //將數據右移一位,等待下一此發送 SCL = 1; //拉高SCL,等待從器件讀取SDA Delay2us(); //延時穩定 SCL= 0; //拉低SCL,鉗住總線,准備發送數據 Delay2us(); //延時穩定 } }
七 讀取1個字節
// 功能說明: CPU從I2C總線設備讀取8bit數據 // 返 回 值: 讀到的數據 uint8_t IIC_Read_Byte(uint8_t ack) { uint8_t i,value; /* 讀到第1個bit為數據的bit7 ,先讀高位后讀低位*/ value = 0; for (i = 0; i < 8; i++) { value <<= 1; 數據左移,為下一此讀取騰出位置 SCL = 1; Delay2us(); if (SDA) //如果SDA為1,則value自加 { value++; } SCL = 0; //鉗住總線,准備下一此讀取 Delay2us(); } if(ack==0) //讀取完畢,判斷答應信號 i2c_NAck(); else i2c_Ack(); return value; //返回讀取到的值 }
好了,以上就是模擬IIC的基本使用方法了!