#include
#define uchar unsigned char
#define DELAY5US _nop_(); _nop_(); _nop_(); _nop_(); //延时5us
#define WriteDeviceAddress 0xa0 //写I2C外围器材的寻址地址
#define ReadDeviceAddress 0xa1 //读I2C外围器材的寻址地址
//注:写I2C外围器材的寻址地址为器材的地址,读为器材地址加1
uchar E0; //非应对信号标志位
uchar NACK=0; //过错标志位
//**************************修正硬件时要修正的部分********************************
sbit SDA = P1^0; //模仿数据线
sbit SCL = P1^1; //模仿时钟线
void Start(void) //发动I2C总线子函数
{
SDA=1;
SCL=1;
DELAY5US
SDA=0;
DELAY5US
SCL=0;
}
void Stop(void) //中止I2C总线数据传送子函数
{
SDA=0;
SCL=1;
DELAY5US
SDA=1;
DELAY5US
SCL=0;
}
void Ack(void) //发送应对位子程序
{
SDA=0;
SCL=1;
DELAY5US
SCL=0;
SDA=1;
}
void NoAck(void) //发送非应对位子程序
{
SDA=1;
SCL=1;
DELAY5US
SCL=0;
SDA=0;
}
void TestAck(void) //应对位查看子程序,若检测不到非应对信号,置位E0
{
SDA=1;
SCL=1;
E0=0;
_nop_(); //短延时
if(SDA==1) //假如SDA为1,标明非应对,置位非应对标志E0
E0=1;
SCL=0;
}
void Write8Bit(uchar n) //写一个字节数据子程序,n为待发送的数据
{
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个字节数据子程序
{ //*Wdata为待发送数据的首地址,RomAddress为待I2C外围器材的数据写入首地址,number为写字节的个数
Start(); //发动
Write8Bit(WriteDeviceAddress); //写入器材的寻址地址
TestAck(); //应对查看
if(E0==1)
{
NACK=1; //若非应对标明器材过错或已坏,置过错标志位NACK
return;
}
Write8Bit(RomAddress); //写入I2C器材的数据存储首地址
TestAck(); //应对查看
if(E0==1)
{
NACK=1; //若非应对标明器材过错或已坏,置过错标志位NACK
return;
}
for(;number!=0;number–) //循环,逐一字节发送
{
Write8Bit(*Wdata); //写一个字节
TestAck(); //应对查看
if(E0==1)
{
NACK=1; //若非应对标明器材过错或已坏,置过错标志位NACK
return;
}
Wdata++; //指针添加,指向下一个数据
}
Stop(); //悉数发送完则中止
}
uchar Read8Bit(void) //读一个字节数据子程序
{
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个字节数据子程序
{ //RamAddress为接纳数据缓冲区的首地址,RomAddress为待I2C外围器材的数据读取首地址,bytes为写字节的个数
Start(); //发动
Write8Bit(WriteDeviceAddress); //写入器材的寻址地址
TestAck(); //应对查看
if(E0==1)
{
NACK=1; //若非应对标明器材过错或已坏,置过错标志位NACK
return;
}
Write8Bit(RomAddress); //写入I2C器材内部数据的读取首地址
TestAck(); //应对查看
if(E0==1)
{
NACK=1; //若非应对标明器材过错或已坏,置过错标志位NACK
return;
}
Start(); //重新发动
Write8Bit(ReadDeviceAddress); //写入器材的寻址地址
TestAck(); //应对查看
if(E0==1)
{
NACK=1; //若非应对标明器材过错或已坏,置过错标志位NACK
return;
}
while(bytes!=1) //循环读入字节数据
{
*RamAddress=Read8Bit(); //读入一个字节
Ack(); //应对
RamAddress++; //地址指针递加
bytes–; //待读入数据个数递
}
*RamAddress=Read8Bit(); //读入最终一个字节数据
NoAck(); //非应对
Stop(); //中止
}