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的基本使用方法了!
