對于死太慘"1T"的單片機需要加快延時。建議直接在后面加一個0,I2C就沒有問題了。
這個程序并不是我原創。是ourDEV中某個24C串口操作里面剝離的。感覺蠻好用。不過稍微改變語法,讓它在SDCC中通過。
這個函數支持TEA5767/24C系列串行儲存器的操作。理論是只要是I2C的器件都沒有問題。
該程序在89C52/SDCC v3.1.0中通過,上代碼。
#ifndef __I2C_H__ #define __I2C_H__ //--------------------------------------------------------------- #define I2C_SCL_0 I2C_SCL = 0 #define I2C_SCL_1 I2C_SCL = 1 #define I2C_SDA_0 I2C_SDA = 0 #define I2C_SDA_1 I2C_SDA = 1 //--------------------管腳定義----------------------------------- #define I2C_SCL P1_1 // I2C總線的時鐘信號 #define I2C_SDA P1_2 // I2C總線的數據信號 //--------------------------------------------------------------- #define DELAY_nT 1 // 延時1個機器周期(2+2*DELAY_nT), // (延時時間大于5us,因此機器個數 // 根據晶振頻率而定) void Delay_I2C() { unsigned char t=DELAY_nT; while(--t); } //*********************************************************************** // 函數名稱:I2C_Start() // 功 能:啟動I2C總線 // 入口參數:無 // 出口參數:無 //*********************************************************************** void I2C_Start(void) { I2C_SDA_1; I2C_SCL_1; Delay_I2C(); // 大于5us I2C_SDA_0; Delay_I2C(); // 大于5us I2C_SCL_0; Delay_I2C(); // 大于5us } //*********************************************************************** // 函數名稱:I2C_Stop() // 功 能:終止I2C總線 // 入口參數:無 // 出口參數:無 //*********************************************************************** void I2C_Stop(void) { /*I2C_SDA_0; I2C_SCL_1; t = DELAY_nT; while(--t); // 大于4us I2C_SDA_1; t = DELAY_nT; while(--t); // 大于5us I2C_SCL_0; t = DELAY_nT; while(--t); // 大于5us I2C_SCL_1;*/ I2C_SCL_0; I2C_SDA_0; Delay_I2C(); // 大于5us I2C_SCL_1; Delay_I2C(); // 大于5us I2C_SDA_1; Delay_I2C(); // 大于5us } //*********************************************************************** // 函數名稱:I2C_Send_Bit_0() // 功 能:發送比特0 // 入口參數:無 // 出口參數:無 //*********************************************************************** void I2C_Send_Bit_0(void) { I2C_SDA_0; I2C_SCL_1; Delay_I2C(); // 大于5us // tL = 6us I2C_SCL_0; // t = DELAY_nT; while(--t); // 大于5us } //*********************************************************************** // 函數名稱:I2C_Send_Bit_1() // 功 能:發送比特1 // 入口參數:無 // 出口參數:無 //*********************************************************************** void I2C_Send_Bit_1(void) { I2C_SDA_1; I2C_SCL_1; Delay_I2C(); // 大于5us I2C_SCL_0; // Delay_I2C(); // 大于5us } //*********************************************************************** // 函數名稱:I2C_Check_Ack() // 功 能:發送完一個字節后檢驗設備的應答信號 // 入口參數:無 // 出口參數:返回值為True,成功 // 返回值為False,失敗 //*********************************************************************** unsigned char I2C_Check_Ack(void) { I2C_SDA_1; I2C_SCL_1; Delay_I2C(); // 大于5us F0 = I2C_SDA; Delay_I2C(); // 大于5us I2C_SCL_0; Delay_I2C(); // 大于5us if( F0 == 1 ) return FALSE; else return TRUE; } //*********************************************************************** // 函數名稱:I2C_Write8Bit() // 功 能:向I2C總線寫入8bit數據 // 入口參數:I2C_data 將要寫入I2C總線的8bit數據 // 出口參數:無 //*********************************************************************** void I2C_Write8Bit(unsigned char I2C_data) { unsigned char i; for( i=0;i<8;i++ )//秒懂。好猥瑣的寫法,致遠吐糟ing { if( (I2C_data<<i)&0x80 ) I2C_Send_Bit_1(); else I2C_Send_Bit_0(); } } //*********************************************************************** // 函數名稱:I2C_Read8Bit() // 功 能:從I2C總線接收8bit數據 // 入口參數:無 // 出口參數:返回值為從I2C總線上接收到的8bit數據 //*********************************************************************** unsigned char I2C_Read8Bit(void) { unsigned char t,I2C_data = 0,i; for( i = 0; i < 8; i++ ) { I2C_data = I2C_data << 1; I2C_SDA_1; I2C_SCL_1; t = DELAY_nT; while(--t); F0 = I2C_SDA; t = DELAY_nT; while(--t); I2C_SCL_0; if( F0 == 1 ) I2C_data = I2C_data | 0x01; } return I2C_data; } #endif
歡迎光臨 (http://www.zg4o1577.cn/bbs/) | Powered by Discuz! X3.1 |