[]()# IIC概述
IIC:兩線式串行總線,它是由__數(shù)據(jù)線SDA__和__時鐘線__SCL構成的串行總線,可發(fā)送和接收數(shù)據(jù),其使用IO使用較少,
在CPU與被控IC之間、IC與IC之間進行雙向傳送,高速IIC總線一般可達400kbs以上。
時鐘線SCL:在通信過程起到控制作用。
數(shù)據(jù)線SDA:用來一位一位的傳送數(shù)據(jù)。
IIC分為軟件IIC和硬件IIC
軟件IIC:軟件IIC通信指的是用單片機的兩個I/O端口模擬出來的IIC,用軟件控制管腳狀態(tài)以模擬I2C通信波形,軟件模擬寄存器的工作方式。
硬件IIC:一塊硬件電路,硬件I2C對應芯片上的I2C外設,有相應I2C驅(qū)動電路,其所使用的I2C管腳也是專用的,硬件(固件)I2C是直接調(diào)用內(nèi)部寄存器進行配置。
補充 :
1.硬件I2C的效率要遠高于軟件的,而軟件I2C由于不受管腳限制,接口比較靈活。
2.IIC是半雙工通信方式
[]()# IIC通信協(xié)議
IIC通信過程由開始、結束、發(fā)送、響應、接收五個部分構成。
1、(在發(fā)送、接收數(shù)據(jù)的時候)當SCL為高電平時,SDA線不允許變化;當SCL線為低電平時,SDA線可以任意0、1變化。
2、(在任意時候)只有當SCL為高電平時,IIC電路才對SDA線上的電平(0或者1)進行記錄,當SCL線為低電平時,無論SDA是高還是低,IIC電路都不對SDA進行采樣。
[]()### 空閑狀態(tài)
在介紹上面五個部分前,我們首先說說空閑狀態(tài),什么是空閑狀態(tài),就是__沒有通信時的狀態(tài)__( 初始狀態(tài) )
I2C總線的SDA和SCL兩條信號同時處于高電平時,規(guī)定為總線的空閑狀態(tài)。此時各個器件的輸出級場效管均處在截止狀態(tài),即釋放總線,由兩條信號線各自的上拉電阻把電平拉高。
[]()### 開始信號與停止信號
開始信號:當SCL為高期間,SDA由高到低的跳變;啟動信號是一種電平跳變時序信號,而不是一個電平。
停止信號:當SCL為高期間,SDA由低到高的跳變;停止信號也是一種電平跳變時序信號,而不是一個電平信號。
開始信號程序 :
//產(chǎn)生IIC起始信號
//1.設置SDA輸出
//2.先拉高SDA,再拉高SCL,空閑狀態(tài)
//3.拉低SDA
//4.準備接收數(shù)據(jù)
void IIC_Start(void)
{
SDA_OUT(); //sda線輸出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//鉗住I2C總線,準備發(fā)送或接收數(shù)據(jù)
}
停止信號程序 :
//產(chǎn)生IIC停止信號
//1.設置SDA輸出
//2.先拉低SDA,再拉低SCL
//3.拉高SCL
//4.拉高SDA
//5.停止接收數(shù)據(jù)
void IIC_Stop(void)
{
SDA_OUT();//sda線輸出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//發(fā)送I2C總線結束信號
delay_us(4);
}
[]()### 應答信號
發(fā)送器每發(fā)送一個字節(jié),就在時鐘脈沖9期間釋放數(shù)據(jù)先,由接收器反饋一個應答信號。應答信號為低電平時,規(guī)定為有效應答位(ACK簡稱應答位),表示接收器已經(jīng)成功接收了該字節(jié);應答信號為高電平時,規(guī)定為非應答位(NACK),一般表示接收器接收該字節(jié)沒有成功。
對于反饋有效應答位ACK的要求是,接收器在第9個時鐘脈沖之前的低電平期間將SDA線拉低,并且確保在該時鐘的高電平期間位穩(wěn)定的低電平。如果接收器是主控器,則在它收到最后一個字節(jié)后,發(fā)送一個NACK信號,以通知被控發(fā)送器結束數(shù)據(jù)發(fā)送,并釋放SDA線,以便主控接收器發(fā)送一個停止信號P
每當主機向從機發(fā)送完一個字節(jié)的數(shù)據(jù),主機總是需要等待從機給出一個應答信號,以確認從機是否成功接收到了數(shù)據(jù),從機應答主機所需要的時鐘仍是主機提供的,應答出現(xiàn)在每一次主機完成8個數(shù)據(jù)位傳輸后緊跟著的時鐘周期,低電平0表示應答,1表示非應答:
應答信號程序 :
//產(chǎn)生ACK應答
//這里就很清楚了,產(chǎn)生應答:SCL在SDA一直為低電平期間完成低高電平轉換
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不產(chǎn)生ACK應答,購買正品元器件,上唯樣商城
//這里就很清楚了,不產(chǎn)生應答:SCL在SDA一直為高電平期間完成低高電平轉換
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
[]()### 發(fā)送數(shù)據(jù)
在I2C總線上傳送的每位數(shù)據(jù)都有一個時鐘脈沖相對應(或同步控制),即在SCL串行時鐘的配合下,SDA逐位地串行傳送每一位數(shù)據(jù)。數(shù)據(jù)位的傳輸是邊沿觸發(fā)。
//IIC發(fā)送一個字節(jié)
//返回從機有無應答
//1,有應答
//0,無應答
//IIC_SCL=0;
//在SCL上升沿時準備好數(shù)據(jù),進行傳送數(shù)據(jù)時,拉高拉低SDA,因為傳輸一個字節(jié),一個SCL脈沖里傳輸一個位。
//數(shù)據(jù)傳輸過程中,數(shù)據(jù)傳輸保持穩(wěn)定(在SCL高電平期間,SDA一直保持穩(wěn)定,沒有跳變)
//只有當SCL被拉低后,SDA才能被改變
//總結:在SCL為高電平期間,發(fā)送數(shù)據(jù),發(fā)送8次數(shù)據(jù),數(shù)據(jù)為1,SDA被拉高,數(shù)據(jù)為0,SDA被拉低。
//傳輸期間保持傳輸穩(wěn)定,所以數(shù)據(jù)線僅可以在時鐘SCL為低電平時改變。
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低時鐘開始數(shù)據(jù)傳輸
for(t=0;t<8;t++)
{
//IIC_SDA=(txd&0x80)>>7;
//獲取數(shù)據(jù)的最高位,然后左移7位
//如果某位為1,則SDA為1,否則相反
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //對TEA5767這三個延時都是必須的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
單片機發(fā)送完一個字節(jié)后面必須跟一個等外應答函數(shù):
思路:先讓SDA=1,再判斷在一定時間內(nèi)SDA是否變?yōu)?,從而識別出外設有沒有發(fā)送應答信號。
//等待應答信號到來
//返回值:1,接收應答失敗
// 0,接收應答成功
//1.設置SDA為輸入
//2.拉高SDA
//3.拉高SCL
//4.等待接收器返回應答信號,如果數(shù)據(jù)線SDA一直為高,就一直等待,并返回1(無效應答),如果數(shù)據(jù)線SDA為低,返回0(有效應答)
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA設置為輸入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//時鐘輸出0
return 0;
}
[]()### 接收數(shù)據(jù)
發(fā)送數(shù)據(jù)是一位一位發(fā)送,接收數(shù)據(jù)也是一位一位接收進來,最后返回應答信號:
//讀1個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK
//先拉低SCL,延時后拉高
//讀取數(shù)據(jù)
//是否發(fā)送應答
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA設置為輸入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//發(fā)送nACK
else
IIC_Ack(); //發(fā)送ACK
return receive;
}
[]()
-
單片機
+關注
關注
6067文章
44961瀏覽量
648895 -
總線
+關注
關注
10文章
2958瀏覽量
89538 -
IIC
+關注
關注
11文章
306瀏覽量
39356
發(fā)布評論請先 登錄
通信技術基礎知識介紹
串行通信基礎知識與UART驅(qū)動構件使用方法
電子通信技術基礎知識
一文深入理解IIC通信基礎知識

評論