作者:Liklon IIC 即Inter-Integrated Circuit(集成電路總線),這種總線類型是由飛利浦半導體公司在八十年代初設計出來的,主要是用來連接整體電路(ICS) ,IIC是一種多向控制總線,也就是說多個芯片可以連接到同一總線結構下,同時每個芯片都可以作為實時數據傳輸的控制源。這種方式簡化了信號傳輸總線。 I2C串行總線一般有兩根信號線,一根是雙向的數據線SDA,另一根是時鐘線SCL。所有接到I2C總線設備上的串行數據SDA都接到總線的SDA上,各設備的時鐘線SCL接到總線的SCL上。以51單片機和AT24C02介紹IO模擬IIC通信。 啟始與停止 啟始條件:必須在所有命令之前發送,時鐘線保持高電平期間,數據線電平從高到低的跳變作為IIC總線的啟動信號。 停止條件:時鐘線保持高電平期間,數據線電平從低到高的跳變作為IIC總線的停止信號。操作結束時必須發送停止條件。 void startbit() { clrSCL(); setSDA(); setSCL(); //時鐘為高時 clrSDA(); //SDA下降沿 clrSCL(); } void stopbit() { clrSCL(); clrSDA(); setSCL(); //時鐘為高時 setSDA(); //SDA上升沿 clrSCL(); } 應答信號 每次數據傳送成功后,從設備發送一個應答信號。當第九個時鐘信號產生時,產生應答信號的器件將SDA下拉為低,通知已經接收到8位數據。 void respond() { unsigned char i = 0; setSDA(); //釋放總線 setSCL(); //時鐘 while(SDA != 0) { i++; if(i > 200) break; } clrSCL(); } 讀寫字節操作 IIC總線協議定義如下: 1. 只有在總線非忙時才被允許進行數據傳輸。 2. 在數據傳輸時,當時鐘線為高電平,數據線必須為固定狀態,不允許跳變,時鐘線為高電平時數據線的任何電平變化都會被當做總線的啟動或停止條件 void writeByte(unsigned char dat) { unsigned char i = 0; for(i = 0;i < 8;i++) { clrSCL(); //拉低時鐘線,改變SDA線的電平 if(dat & 0x80) setSDA(); else clrSDA(); setSCL(); //SDA電平穩定后,拉高時鐘線 dat <<= 1; } clrSCL(); } unsigned char readByte() { unsigned char i = 0,tmp = 0; for(i = 0;i < 8;i++) { clrSCL(); //拉低時鐘線 tmp <<= 1; //準備讀取數據 setSCL(); //拉高時鐘線 if(SDA) tmp |= 0x01; } clrSCL(); return tmp; } AT24C02讀寫操作 void writeAT24XX(unsigned char addr,unsigned char dat) { startbit(); //起始信號 writeByte(0xa0); //器件地址 respond(); writeByte(addr); //器件內部地址 respond(); writeByte(dat); //數據 respond(); stopbit(); //停止 } unsigned char readAT24XX(unsigned char addr) { unsigned char dat; startbit(); //起始信號 writeByte(0xa0); //器件地址 respond(); writeByte(addr); //器件內部地址 respond(); startbit(); //起始信號 writeByte(0xa1); //器件地址 respond(); dat = readByte(); //數據 stopbit(); //停止 return dat; } 主函數部分內容以及程序運行效果: void main() { unsigned char dat; initUart(); sendString("UART INIT OK!!!\n"); //串口通信初始化 sendString("write 0x05 --> addr 0x00 \n");//寫入5到期間內部地址0 writeAT24XX(0x00,0x05); //寫入數據 sendString("read dat <-- addr 0x00 \n"); //讀出寫入數據 dat = readAT24XX(0x00); //讀出數據 sendString("dat-->"); //打印 sendByte(dat + '0'); while(1); } |