51單片機進階開發(fā)(五)之IIC通信

再話單片機通信
前面的文章中已經(jīng)介紹了單片機的并口通信和UART串口通信,在實際開發(fā)過程中我們還可能用到很多其他通信協(xié)議,IIC協(xié)議就是其中常見的一種,它的用途很廣,很多資料都講得比較專業(yè)化,這篇文章我們一起通過簡單的文字來熟悉它,以后應用時再講專業(yè)點。
何為IIC
IIC總線全稱是Inter Integrated Circuit總線,也寫做I^2C總線,它是由飛利浦公司推出的一種同步通信協(xié)議,這種協(xié)議只用兩根通信引腳,一根信號線SDA,另一根時鐘線SCL,即它使用兩根信號線就可實現(xiàn)全雙工的同步數(shù)據(jù)傳輸??傊?,它具有接口線少、占用資源小、控制簡單、通信速率較高等優(yōu)點。至于為什么,現(xiàn)在我們先不用管,等后面介紹完其他通信協(xié)議后再做對比了解。
所有與IIC兼容的器件都具有標準的接口,可以把多個IIC總線器件同時接到IIC總線上。當然,因為IIC協(xié)議比較簡單,所以我們使用時通常也會直接通過軟件模擬協(xié)議來實現(xiàn),特別是對于沒有IIC接口的單片機,比如普通51,52單片機。在總線上通過地址來識別通信對象,使它們可以之間可以通過IIC總線直接通信,總線上的各設備具有唯一的識別地址,正是因為具備通信識別功能,并且簡單容易實現(xiàn),使得它在電子領域有非常廣的應用,比如各種低速存儲IC,各類傳感器等等。

因為所有IIC通信引腳內(nèi)部電路使用的是開漏結構,所以在實際應用中需要對其引腳添加上拉電阻,以保證正常通信

通信協(xié)議總覽
IIC總線協(xié)議上的設備分主設備和從設備,猶如常說的主機和從機,顧名思義,主設備是發(fā)送命令或數(shù)據(jù)的器件,從設備為接收命令或向主設備傳送數(shù)據(jù)的器件。并且主設備控制時鐘信號,從設備根據(jù)主設備的時鐘信號和地址信息進行響應。
主從設備之間還需要遵循一定的規(guī)則:
IIC總線空閑狀態(tài)下,SCL和SDA均為高電平,只有在總線空閑時才允許啟動數(shù)據(jù)傳送。
起始信號:鐘線SCL為高電平時,數(shù)據(jù)線SDA從高電平到低電平的跳變被定義為起始信號。
停止信號:時鐘線SCL為高電平時,數(shù)據(jù)線SDA從低電平到高電平的跳變被定義為停止信號。
除以上被定義的起始信號和停止信號外,數(shù)據(jù)傳送過程,時鐘線為高電平時,數(shù)據(jù)線必須保持穩(wěn)定狀態(tài),即時鐘線為高電平時,數(shù)據(jù)線的任何電平變化都將被看作總線的起始或停止信號。

通信一般步驟
發(fā)送命令:
發(fā)送起始(START)信號;
發(fā)送設備地址;
等待從設備響應(ACK);
發(fā)送數(shù)據(jù),一般情況每發(fā)送一個字節(jié)數(shù)據(jù)后會等待接收來自從設備的響應(ACK)信號;
數(shù)據(jù)發(fā)送完畢,發(fā)送停止(STOP)信號,終止傳輸。
讀取命令:
發(fā)送起始(START)信號;
發(fā)送設備地址;
等待從設備響應(ACK);
接收來自從設備的數(shù)據(jù),一般情況下每接收一個字節(jié)數(shù)據(jù)后會向從設備發(fā)送一個響應(ACK)信號;
接收到最后一個數(shù)據(jù),發(fā)送一個無效響應(NACK),然后發(fā)送停止(STOP)信號,終止傳輸。
通信程序舉例
1.總線初始化
void?init()
{
??SCL=?1;
??delay?();
??SDA=?1;
??delay?();
}
2.起始信號
void?start()?????????????????????
{
??SDA=?1;
??delay?();
??SCL=?1;
??delay?();
??SDA=?0;
??delay?();
}
3.應答信號
void?respons()
{
??uchar?i=?0;
??SCL=?1;
??delay();
??while?((SDA==?1)&&(i<?255))
??{
????i++?;
??}
??SCL=?0;
??delay();
}
4.停止信號
void?stop()?
{
??SDA=?0;
??delay();
??SCL=?1;
??delay();
??SDA=?1;
??delay();
}
5.寫數(shù)據(jù)
void?writebyte(uchar?date)
{
??uchar?i,temp;
??temp=?date;
??for(i=?0;i<?8;i++?)
??{
????temp=?temp<<?1;?
????SCL=?0;
????delay();
????SDA=?CY;
????delay();
????SCL=?1;
????delay();
??}
??SCL=?0;
??delay();
??SDA=?1;
??delay();
}
6.讀數(shù)據(jù)
void?readbyte()?????????????
{
??uchar?i,k;
??SCL=?0;
??delay();
??SDA=?1;
??for(i=?0;i<?8;i++?)?????????
??{
????SCL=?1;
????delay();
????k=?(k<<?1)|SDA;????????????
????SCL=?0;
????delay();
??}
??delay();
??return?k;???????????????????
}
