|
1.IIC總線是由數(shù)據(jù)線SDA和時(shí)鐘SCL構(gòu)成的串行總線,可發(fā)送和接收數(shù)據(jù)。它在傳輸數(shù)據(jù)過程中有三種特殊類型信號(hào),分別是:開始信號(hào)、結(jié)束信號(hào)和應(yīng)答信號(hào)。
區(qū)分UART通信:同樣使用兩根線進(jìn)行數(shù)據(jù)傳輸,但UART通信中一根用于接收數(shù)據(jù),一根用于發(fā)送數(shù)據(jù),每次通信的時(shí)候只用到一根線。且其傳輸數(shù)據(jù)與時(shí)鐘無關(guān),因此稱為異步串行通信,隨時(shí)進(jìn)行數(shù)據(jù)的接收和發(fā)送,SBUF寄存器存滿時(shí),則說明完成數(shù)據(jù)接收;想要進(jìn)行數(shù)據(jù)發(fā)送時(shí),只需把數(shù)據(jù)寫入SBUF寄存器。
IIC通信:IIC通信無論發(fā)送還是接收,都需要結(jié)合時(shí)鐘SCL來進(jìn)行數(shù)據(jù)SDA的傳輸,因此一次要使用兩條線。傳輸數(shù)據(jù)與時(shí)鐘有關(guān),因此稱為同步串行通信。
2.IIC通信的起始信號(hào)和停止信號(hào)
時(shí)鐘線SCL為高電平期間,數(shù)據(jù)線SDA由高電平向低電平變化——起始信號(hào)
時(shí)鐘線SCL為高電平期間,數(shù)據(jù)線SDA由低電平向高電平變化——停止信號(hào)
3.IIC通信的數(shù)據(jù)傳輸
時(shí)鐘線SCL為高電平期間,數(shù)據(jù)線SDA上的數(shù)據(jù)必須保持穩(wěn)定。
只有時(shí)鐘線SCL信號(hào)為低電平期間,數(shù)據(jù)線SDA狀態(tài)才允許變化。 4.數(shù)據(jù)線SDA上的數(shù)據(jù)一般先于時(shí)鐘SCL發(fā)生變化
原因:發(fā)生變化說明信號(hào)需要翻轉(zhuǎn),分兩種情況(數(shù)據(jù)線SDA隨你怎么翻)。情況1-1:當(dāng)數(shù)據(jù)線SDA先發(fā)生變化,時(shí)鐘線SCL再從1變?yōu)?,與上述第3點(diǎn)相違背,在時(shí)鐘SCL為高電平時(shí),數(shù)據(jù)線SDA并沒有保持穩(wěn)定,而發(fā)生翻轉(zhuǎn),這樣的信號(hào)只會(huì)被當(dāng)做是起始信號(hào)或停止信號(hào);
情況1-2:數(shù)據(jù)線SDA還是先發(fā)生變化,時(shí)鐘線SCL從0變1,在時(shí)鐘線SCL為0時(shí),數(shù)據(jù)線SDA早已經(jīng)完成了翻轉(zhuǎn),也就是說,在時(shí)鐘線SCL為0時(shí),數(shù)據(jù)線沒有發(fā)生變化,那么在后來時(shí)鐘線SCL為1時(shí),所傳輸?shù)臄?shù)據(jù)則是數(shù)據(jù)線SDA上剛完成翻轉(zhuǎn)后的數(shù)據(jù)。情況2-1:時(shí)鐘線SCL由0變1,先于數(shù)據(jù)線SDA發(fā)生變化,時(shí)鐘線SCL低電平時(shí)的狀態(tài)內(nèi),數(shù)據(jù)線SDA沒有發(fā)生任何變化,所以只在最后維持高電平有效,而在高電平后,再改變數(shù)據(jù)線SDA的數(shù)據(jù),違反了上述第3點(diǎn);
情況2-2:時(shí)鐘線SCL由1變0,先于數(shù)據(jù)線SDA發(fā)生變化,在變0之后,數(shù)據(jù)線SDA會(huì)完成信號(hào)的翻轉(zhuǎn)。在之后得等時(shí)鐘線SCL重新置1,才能確認(rèn)數(shù)據(jù)線SDA的傳輸數(shù)據(jù)----那如果這樣的話,不就又變成了數(shù)據(jù)線SDA先變化,時(shí)鐘線SCL后變化的情況了??
綜上所述,去除掉違反IIC數(shù)據(jù)傳輸?shù)囊?guī)則的兩則情況后,剩下的紅色兩種情況,則是現(xiàn)在第4點(diǎn)的最好說明...
5.IIC的數(shù)據(jù)讀寫和應(yīng)答
區(qū)分UART數(shù)據(jù)傳輸:UART數(shù)據(jù)傳輸先傳低位,后傳高位
IIC數(shù)據(jù)傳輸:先傳高位,后傳低位
主機(jī)寫數(shù)據(jù)時(shí),每發(fā)送一個(gè)字節(jié),接收機(jī)需要回復(fù)一個(gè)應(yīng)答位“0”,通過應(yīng)答位來判斷從機(jī)是否接收成功
主機(jī)讀數(shù)據(jù)時(shí),接收一個(gè)字節(jié)結(jié)束后,主機(jī)也需要發(fā)一個(gè)應(yīng)答位“0”,但是當(dāng)接收最后一個(gè)字節(jié)結(jié)束后,需要發(fā)送一個(gè)非應(yīng)答位“1”,發(fā)完這個(gè)非應(yīng)答位“1”后,再發(fā)一個(gè)停止信號(hào),最終結(jié)束通信。
如果需要檢測(cè)應(yīng)答信號(hào)“0”,得先置高數(shù)據(jù)線SDA,如果數(shù)據(jù)線后來檢測(cè)到應(yīng)答信號(hào)“0”,則是應(yīng)答信號(hào)存在的最好說明!
如果需要檢測(cè)非應(yīng)答信號(hào)“1”,得先拉低數(shù)據(jù)線SDA,如果數(shù)據(jù)線后來檢測(cè)到非應(yīng)答信號(hào)“1”,也是非應(yīng)答信號(hào)存在的最好說明!
6.IIC協(xié)議傳輸一位數(shù)據(jù)程序分析
void Delay(void) //在使用IIC進(jìn)行通信的時(shí)候,需要控制傳輸數(shù)據(jù)的速度,這里的使用了4個(gè)機(jī)器周期的延時(shí),而具體的延時(shí)由于包括了函
{ //數(shù)調(diào)用時(shí)的壓棧和出棧,而且受編譯環(huán)境的影響,因此實(shí)際延時(shí)并不止4個(gè)機(jī)器周期
_nop_() ;_nop_() ;_nop_() ;_nop_() ;
}
void IIC_Send_Byte(unsigned char byte) //有數(shù)據(jù)傳入,類型為八位無符號(hào)字節(jié)型——傳入數(shù)據(jù) / 命令 / 地址
{
unsigned char mask, i; //定義兩個(gè)八位無符號(hào)字節(jié)型變量,一個(gè)用以for循環(huán),另一個(gè)用以把傳入的十六進(jìn)制數(shù),以二進(jìn)制方式提取各個(gè)位
mask = 0x80;//再結(jié)合時(shí)鐘線SCL時(shí)序變化,控制數(shù)據(jù)線SDA進(jìn)行信號(hào)傳輸
for(i = 0; i < 8; i++)
{
SCL = 0; //先把時(shí)鐘線SCL置“0”,為了使數(shù)據(jù)線SDA數(shù)據(jù)能變化
Delay(); //數(shù)據(jù)傳輸?shù)难訒r(shí)
if((mask & byte) == 0) //用mask十六進(jìn)制數(shù)(以二進(jìn)制的方式)與傳入的數(shù)據(jù)byte取“與”,把傳入的十六進(jìn)制byte以二進(jìn)制的方式提取位
{
SDA = 0;//如果該位取“與”為0,則控制數(shù)據(jù)線SDA數(shù)據(jù)變?yōu)?
}
else
{
SDA = 1; //否則如果該位取“與”為1,則控制數(shù)據(jù)線SDA數(shù)據(jù)變?yōu)?
}
mask >>= 1; //mask變量右移一位,假如第一次mask值為1000 0000,完成數(shù)據(jù)線SDA的一次輸出后,mask的值為0100 0000,方便
Delay(); //繼續(xù)提取第二位數(shù)據(jù),數(shù)據(jù)傳輸?shù)难訒r(shí)
SCL= 1; //在時(shí)鐘線SCL為1的時(shí)候維持?jǐn)?shù)據(jù)SDA的穩(wěn)定,便能確認(rèn)傳入的數(shù)據(jù)
Delay(); //數(shù)據(jù)傳輸?shù)难訒r(shí)
}
SCL = 0; //先置低時(shí)鐘線SCL,才能拉高數(shù)據(jù)線SDA,用以檢測(cè)后面的應(yīng)答信號(hào)
SDA= 1;
Delay();
SCL= 1; //下面對(duì)時(shí)鐘線SCL的操縱則是用以檢測(cè)應(yīng)答信號(hào)的
Delay();
SCL= 0;
}
|
|