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