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