模擬I2C程序設(shè)計
#define uchar unsigned char
#define DELAY5US _nop_(); _nop_(); _nop_(); _nop_(); //延時5us
#define WriteDeviceAddress 0xa0 //寫I2C外圍器件的尋址地址
#define ReadDeviceAddress 0xa1 //讀I2C外圍器件的尋址地址
//注:寫I2C外圍器件的尋址地址為器件的地址,讀為器件地址加1
uchar E0; //非應(yīng)答信號標(biāo)志位
uchar NACK=0; //錯誤標(biāo)志位
//**************************修改硬件時要修改的部分********************************
sbit SDA = P1^0; //模擬數(shù)據(jù)線
sbit SCL = P1^1; //模擬時鐘線
void Start(void) //啟動I2C總線子函數(shù)
{
SDA=1;
SCL=1;
DELAY5US
SDA=0;
DELAY5US
SCL=0;
}
void Stop(void) //停止I2C總線數(shù)據(jù)傳送子函數(shù)
{
SDA=0;
SCL=1;
DELAY5US
SDA=1;
DELAY5US
SCL=0;
}
void Ack(void) //發(fā)送應(yīng)答位子程序
{
SDA=0;
SCL=1;
DELAY5US
SCL=0;
SDA=1;
}
void NoAck(void) //發(fā)送非應(yīng)答位子程序
{
SDA=1;
SCL=1;
DELAY5US
SCL=0;
SDA=0;
}
void TestAck(void) //應(yīng)答位檢查子程序,若檢測不到非應(yīng)答信號,置位E0
{
SDA=1;
SCL=1;
E0=0;
_nop_(); //短延時
if(SDA==1) //如果SDA為1,表明非應(yīng)答,置位非應(yīng)答標(biāo)志E0
E0=1;
SCL=0;
}
void Write8Bit(uchar n) //寫一個字節(jié)數(shù)據(jù)子程序,n為待發(fā)送的數(shù)據(jù)
{
uchar i;
for(i=8;i>0;i--)
{
SDA=(bit)(n&0x80);
SCL=1;
DELAY5US
SCL=0;
SDA=0;
n=n<<1;
}
}
void WriteI2C(uchar *Wdata,uchar RomAddress,uchar number) // 寫n個字節(jié)數(shù)據(jù)子程序
{ //*Wdata為待發(fā)送數(shù)據(jù)的首地址,RomAddress為待I2C外圍器件的數(shù)據(jù)寫入首地址,number為寫字節(jié)的個數(shù)
Start(); //啟動
Write8Bit(WriteDeviceAddress); //寫入器件的尋址地址
TestAck(); //應(yīng)答檢查
if(E0==1)
{
NACK=1; //若非應(yīng)答表明器件錯誤或已壞,置錯誤標(biāo)志位NACK
return;
}
Write8Bit(RomAddress); //寫入I2C器件的數(shù)據(jù)存儲首地址
TestAck(); //應(yīng)答檢查
if(E0==1)
{
NACK=1; //若非應(yīng)答表明器件錯誤或已壞,置錯誤標(biāo)志位NACK
return;
}
for(;number!=0;number--) //循環(huán),逐個字節(jié)發(fā)送
{
Write8Bit(*Wdata); //寫一個字節(jié)
TestAck(); //應(yīng)答檢查
if(E0==1)
{
NACK=1; //若非應(yīng)答表明器件錯誤或已壞,置錯誤標(biāo)志位NACK
return;
}
Wdata++; //指針增加,指向下一個數(shù)據(jù)
}
Stop(); //全部發(fā)送完則停止
}
uchar Read8Bit(void) //讀一個字節(jié)數(shù)據(jù)子程序
{
uchar temp,rbyte=0;
for(temp=8;temp>0;temp--)
{
SDA=1;
SCL=1;
_nop_(); //短延時
rbyte=rbyte<<1;
rbyte=rbyte|((uchar)(SDA));
SCL=0;
}
return(rbyte);
}
void ReadI2C(uchar *RamAddress,uchar RomAddress,uchar bytes) // 讀n個字節(jié)數(shù)據(jù)子程序
{ //RamAddress為接收數(shù)據(jù)緩沖區(qū)的首地址,RomAddress為待I2C外圍器件的數(shù)據(jù)讀取首地址,bytes為寫字節(jié)的個數(shù)
Start(); //啟動
Write8Bit(WriteDeviceAddress); //寫入器件的尋址地址
TestAck(); //應(yīng)答檢查
if(E0==1)
{
NACK=1; //若非應(yīng)答表明器件錯誤或已壞,置錯誤標(biāo)志位NACK
return;
}
Write8Bit(RomAddress); //寫入I2C器件內(nèi)部數(shù)據(jù)的讀取首地址
TestAck(); //應(yīng)答檢查
if(E0==1)
{
NACK=1; //若非應(yīng)答表明器件錯誤或已壞,置錯誤標(biāo)志位NACK
return;
}
Start(); //重新啟動
Write8Bit(ReadDeviceAddress); //寫入器件的尋址地址
TestAck(); //應(yīng)答檢查
if(E0==1)
{
NACK=1; //若非應(yīng)答表明器件錯誤或已壞,置錯誤標(biāo)志位NACK
return;
}
while(bytes!=1) //循環(huán)讀入字節(jié)數(shù)據(jù)
{
*RamAddress=Read8Bit(); //讀入一個字節(jié)
Ack(); //應(yīng)答
RamAddress++; //地址指針遞增
bytes--; //待讀入數(shù)據(jù)個數(shù)遞
}
*RamAddress=Read8Bit(); //讀入最后一個字節(jié)數(shù)據(jù)
NoAck(); //非應(yīng)答
Stop(); //停止
}
評論