根据I2C协议,本人写的符合协议的代码,已经在8051上面挂了一个I2C从机,测试通过,使用逻辑分析仪来分析数据,结果表明符合,符合协议内容。。贴出代码,供大家交流,共同进步。。。
适合于普通模式,主机的时钟频率大概在120K左右。。
因为是C语言,对时间的控制不是很精确。。。
#include "reg51.h"
#include "intrins.h"
sbit SCL= P1^7;
sbit SDA= P1^6;
void Start_I2C(void)
{
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}
void Stop_I2C (void)
{
SDA=0;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
bit SendAck(void)
{
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
return(1);
}
bit DetectAck(void)
{
unsigned char errtime = 255;
SDA = 1;
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
while(SDA)
{
errtime--;
if(errtime==0)
{
Stop_I2C();
return(0);
}
}
SCL = 0;
_nop_();
return(1);
}
void Send_I2C (unsigned char ch)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCL=0;
_nop_();
_nop_();
SDA=(ch&0x80);
ch<<=1;
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
}
SCL=0;
}
unsigned char Receive_I2C(void)
{
unsigned char i,data_in=0;
SDA=1;
for (i=0;i<8;i++)
{
data_in<<=1;
SCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
data_in|=SDA;
}
SCL=0;
return data_in;
}
void write(unsigned char regaddress,unsigned char data0)
{
Start_I2C();
Send_I2C(0x98);
if(DetectAck())
{
Send_I2C(regaddress);
if(DetectAck())
{
Send_I2C(data0);
if(DetectAck())
Stop_I2C();
}
else
Stop_I2C();
}
else
Stop_I2C();
}
void read(unsigned char regaddress)
{
Start_I2C();
Send_I2C(0x98);
if(DetectAck())
{
Send_I2C(regaddress);
if(DetectAck())
{
Start_I2C();
Send_I2C(0x99);
if(DetectAck())
{
P2=Receive_I2C();
Stop_I2C();
}
else Stop_I2C();
}
else Stop_I2C();
}
else
Stop_I2C();
}
void write_read(unsigned char regaddress,unsigned char data0)
{
write(regaddress, data0);
read(regaddress);
}
void doublebyte_write_read(unsigned char baseaddress,unsigned char data1,unsigned char data2)
{
Start_I2C();
Send_I2C(0x98);
if(DetectAck())
{
Send_I2C(baseaddress);
if(DetectAck())
{
Send_I2C(data1);
if(DetectAck())
{
Send_I2C(data2);
if(DetectAck())
Stop_I2C();
else Stop_I2C();
}
else Stop_I2C();
}
else Stop_I2C();
}
else
Stop_I2C();
Start_I2C();
Send_I2C(0x98);
if(DetectAck())
{
Send_I2C(baseaddress);
if(DetectAck())
{
Start_I2C();
Send_I2C(0x99);
if(DetectAck())
{
P2=Receive_I2C();
SendAck();
P2=Receive_I2C();
Stop_I2C();
}
else Stop_I2C();
}
else Stop_I2C();
}
else Stop_I2C();
}
void main()
{
write_read(0x2D,0xD2);
write_read(0x2E,0xE2);
read(0x3C);
write_read(0x3C,0xCC);
read(0x01);
read(0x02);
doublebyte_write_read(0x01,0x11,0x22);
}