模擬I2C總線軟件包(C51)
/******************************************************************************
I2C.H
標(biāo)準(zhǔn)80C51模擬I2C總線程序頭文件
******************************************************************************/
#ifndef I2C_H
#define I2C_H
//定義I2C操作模式
#define I2C_RECV 0 /* 接收模式 */
#define I2C_SEND 1 /* 發(fā)送模式 */
#define I2C_SrRECV 2 /* 帶Sr接收 */
//I2C總線初始化
void I2C_Init();
/******************************************************************************
函數(shù):void I2C_On()
功能:啟動I2C總線收發(fā)數(shù)據(jù)
返回:0-正常,1-異常(無應(yīng)答)
說明:參數(shù)Mode是操作模式,決定I2C總線收發(fā)格式。常見的收發(fā)格式有3種,具體如下:
0-接收模式,格式:S | SLA+R | Data... | P
1-發(fā)送模式,格式:S | SLA+W | Addr | Data... | P
2-帶Sr接收,格式:S | SLA+W | Addr | Sr | SLA+R | Data... | P
******************************************************************************/
bit I2C_On
(
unsigned char Mode, //操作模式
unsigned char SLA, //從機(jī)地址
unsigned char Addr, //子地址
unsigned char *Buf, //數(shù)據(jù)緩沖區(qū)
unsigned char Size //數(shù)據(jù)長度
);
#endif //I2C_H
/******************************************************************************
I2C.C
標(biāo)準(zhǔn)80C51模擬I2C總線程序(主模式,通用)
******************************************************************************/
#i nclude
#i nclude "I2C.H"
//模擬I2C總線的管腳定義
sbit I2C_SCL = P1^6; //定義I2C總線時(shí)鐘信號
sbit I2C_SDA = P1^7; //定義I2C總線數(shù)據(jù)信號
/******************************************************************************
函數(shù):I2C_Delay()
功能:模擬I2C總線延時(shí)
說明:請根據(jù)具體情況調(diào)整延時(shí)值
******************************************************************************/
void I2C_Delay()
{
unsigned char t;
t = 10;
while ( --t != 0 ); //延時(shí)2*t個(gè)機(jī)器周期
}
/******************************************************************************
函數(shù):I2C_Init()
功能:I2C總線初始化,使總線處于空閑狀態(tài)
說明:在main()函數(shù)的開始處,應(yīng)當(dāng)執(zhí)行一次本函數(shù)
******************************************************************************/
void I2C_Init()
{
I2C_SCL = 1; I2C_Delay();
I2C_SDA = 1; I2C_Delay();
}
/******************************************************************************
函數(shù):I2C_Start()
功能:產(chǎn)生I2C總線的起始條件
說明:SCL處于高電平期間,當(dāng)SDA出現(xiàn)下降沿時(shí)啟動I2C總線
本函數(shù)也用來產(chǎn)生重復(fù)起始條件
******************************************************************************/
void I2C_Start()
{
I2C_SDA = 1; I2C_Delay();
I2C_SCL = 1; I2C_Delay();
I2C_SDA = 0; I2C_Delay();
I2C_SCL = 0; I2C_Delay();
}
/******************************************************************************
函數(shù):I2C_Write()
功能:向I2C總線寫1個(gè)字節(jié)的數(shù)據(jù)
參數(shù):dat是要寫到總線上的數(shù)據(jù)
******************************************************************************/
void I2C_Write(unsigned char dat)
{
unsigned char t = 8;
do
{
I2C_SDA = (bit)(dat & 0x80);
dat <<= 1;
I2C_SCL = 1; I2C_Delay();
I2C_SCL = 0; I2C_Delay();
} while ( --t != 0 );
}
/******************************************************************************
函數(shù):I2C_Read()
功能:從從機(jī)讀取1個(gè)字節(jié)的數(shù)據(jù)
返回:讀取的1個(gè)字節(jié)數(shù)據(jù)
******************************************************************************/
unsigned char I2C_Read()
{
unsigned char dat;
unsigned char t = 8;
I2C_SDA = 1; //在讀取數(shù)據(jù)之前,要把SDA拉高,使之處于輸入狀態(tài)
do
{
I2C_SCL = 1; I2C_Delay();
dat <<= 1;
if ( I2C_SDA ) dat++;
I2C_SCL = 0; I2C_Delay();
} while ( --t != 0 );
return dat;
}
/******************************************************************************
函數(shù):I2C_GetAck()
功能:讀取從機(jī)應(yīng)答位(應(yīng)答或非應(yīng)答),用于判斷:從機(jī)是否成功接收主機(jī)數(shù)據(jù)
返回:0-從機(jī)應(yīng)答
1-從機(jī)非應(yīng)答
說明:從機(jī)在收到每一個(gè)字節(jié)后都要產(chǎn)生應(yīng)答位,主機(jī)如果收到非應(yīng)答則應(yīng)當(dāng)終止傳輸
******************************************************************************/
bit I2C_GetAck()
{
bit Ack;
I2C_SDA = 1; I2C_Delay();
I2C_SCL = 1; I2C_Delay();
Ack = I2C_SDA;
I2C_SCL = 0; I2C_Delay();
return Ack;
}
/******************************************************************************
函數(shù):I2C_PutAck()
功能:主機(jī)產(chǎn)生應(yīng)答位(應(yīng)答或非應(yīng)答),用于通知從機(jī):主機(jī)是否成功接收從機(jī)數(shù)據(jù)
參數(shù):Ack = 0:主機(jī)應(yīng)答
Ack = 1:主機(jī)非應(yīng)答
說明:主機(jī)在收到每一個(gè)字節(jié)后都要產(chǎn)生應(yīng)答,在收到最后一個(gè)字節(jié)時(shí),應(yīng)當(dāng)產(chǎn)生非應(yīng)答
******************************************************************************/
void I2C_PutAck(bit Ack)
{
I2C_SDA = Ack; I2C_Delay();
I2C_SCL = 1; I2C_Delay();
I2C_SCL = 0; I2C_Delay();
}
/******************************************************************************
函數(shù):I2C_Stop()
功能:產(chǎn)生I2C總線的停止條件
說明:SCL處于高電平期間,當(dāng)SDA出現(xiàn)上升沿時(shí)停止I2C總線
******************************************************************************/
void I2C_Stop()
{
I2C_SDA = 0; I2C_Delay();
I2C_SCL = 1; I2C_Delay();
I2C_SDA = 1; I2C_Delay();
}
/******************************************************************************
函數(shù):void I2C_On()
功能:啟動I2C總線收發(fā)數(shù)據(jù)
返回:0-正常,1-異常(無應(yīng)答)
說明:參數(shù)Mode是操作模式,決定I2C總線收發(fā)格式。常見的收發(fā)格式有3種,具體如下:
0-接收模式,格式:S | SLA+R | Data... | P
1-發(fā)送模式,格式:S | SLA+W | Addr | Data... | P
2-帶Sr接收,格式:S | SLA+W | Addr | Sr | SLA+R | Data... | P
******************************************************************************/
bit I2C_On
(
unsigned char Mode, //操作模式
unsigned char SLA, //從機(jī)地址
unsigned char Addr, //子地址
unsigned char *Buf, //數(shù)據(jù)緩沖區(qū)
unsigned char Size //數(shù)據(jù)長度
)
{
//啟動I2C總線
I2C_Start();
if ( Mode != I2C_RECV )
{
//發(fā)送SLA+W
I2C_Write(SLA & 0xFE);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//發(fā)送子地址
I2C_Write(Addr);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
if ( Mode == I2C_SEND )
{
//發(fā)送數(shù)據(jù)
do
{
I2C_Write(*Buf++);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
} while ( --Size != 0 );
//發(fā)送完畢
I2C_Stop();
return 0;
}
else
{
I2C_Start(); //發(fā)送重復(fù)起始條件
}
}
//發(fā)送SLA+R
I2C_Write(SLA | 0x01);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//接收數(shù)據(jù)
for (;;)
{
*Buf++ = I2C_Read();
if ( --Size == 0 )
{
I2C_PutAck(1); //接收完最后一個(gè)數(shù)據(jù)時(shí)發(fā)送NACK
break;
}
I2C_PutAck(0);
}
//接收完畢
I2C_Stop();
return 0;
}