對于死太慘"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.rwzy.co.cc
|