IO口模拟I2C总线读写EEPROM
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用IO口模拟I2C总线与24C256通信,代码如下:
#define SCL TG2
#define SDA TG3
#define SCL_DIR TRISGbits.TRISG2
#define SDA_DIR TRISGbits.TRISG3
#define H_BYTE(wVal) *( (unsigned char*)&wVal+1)
#define L_BYTE(wVal) *( (unsigned char*)&wVal )
#define NOP() asm("nop")
#define INT8U unsigned char
#define INT16U unsigned int
void I2cInit();
void I2c_delay();
void I2cStop();
void I2cStart();
void I2cSendAck();
void I2cSendNack();
INT8U I2cCheckAck();
void WriteOneByte(INT8U cData);
INT8U ReadOneByte();
INT8U WriteI2cData(INT16U addr, INT8U cData);
INT8U ReadI2cData(INT16U addr);
void I2c_delay()
{
NOP();
NOP();
NOP();
NOP();
}
void I2cInit()
{
I2cStop();
I2cStart();
I2cStop();
}
void I2cStart()
{
SCL_DIR = 0;
SDA_DIR = 0;
SCL = 1;
SDA = 1;
I2c_delay();
SDA = 0;
I2c_delay();
SCL = 0;
I2c_delay();
}
void I2cStop()
{
SCL_DIR = 0;
SDA_DIR = 0;
I2c_delay();
SDA = 0;
I2c_delay();
SCL = 1;
I2c_delay();
SDA = 1;
I2c_delay();
}
void I2cSendAck()
{
SDA_DIR = 0;
SDA = 0;
I2c_delay();
SCL = 0;
I2c_delay();
SCL = 1;
I2c_delay();
SCL = 0;
SDA = 1;
}
void I2cSendNack()
{
SDA_DIR = 0;
SDA = 1;
I2c_delay();
SCL = 0;
I2c_delay();
SCL = 1;
I2c_delay();
SCL = 0;
}
INT8U I2cCheckAck()
{
INT8U AckStatus;
SDA_DIR = 1;
SCL = 1;
I2c_delay();
if(SDA == 1)
{
AckStatus = 0;
}
else
{
AckStatus = 1;
}
SCL = 0;
I2c_delay();
return AckStatus;
}
void WriteOneByte(INT8U cData)
{
INT8U i;
SDA_DIR = 0;
for(i=0; i<8; i++)
{
if(cData & 0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
I2c_delay();
SCL = 1;
I2c_delay();
SCL = 0;
I2c_delay();
cData <<= 1;
}
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
}
INT8U ReadOneByte()
{
INT8U cData = 0, i;
SDA_DIR = 1;
SCL = 0;
I2c_delay();
for(i=0; i<8; i++)
{
SCL = 1;
I2c_delay();
cData <<= 1;
if(SDA == 1)
{
cData |= 0x01;
}
else
{
cData &= 0xFE;
}
SCL = 0;
}
SDA_DIR = 0;
return cData;
}
INT8U WriteI2cData(INT16U addr, INT8U cData)
{
INT8U cTemp;
I2cStart();
WriteOneByte(0xa0); //Slave device address
if(I2cCheckAck() == 0)
{
return 0;
}
cTemp = H_BYTE(addr);
WriteOneByte(cTemp);
if(I2cCheckAck() == 0)
{
return 0;
}
cTemp = L_BYTE(addr);
WriteOneByte(cTemp);
if(I2cCheckAck() == 0)
{
return 0;
}
WriteOneByte(cData);
if(I2cCheckAck() == 0)
{
return 0;
}
I2cStop(); //Stop condition
// delay_10us(80);
return 0;
}
INT8U ReadI2cData(INT16U addr)
{
INT8U cTemp;
I2cStart();
WriteOneByte(0xa0);
if(I2cCheckAck() == 0)
{
return 0;
}
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
cTemp = H_BYTE(addr);
WriteOneByte(cTemp);
if(I2cCheckAck() == 0)
{
return 0;
}
I2c_delay();
I2c_
delay();
I2c_delay();
I2c_delay();
cTemp = L_BYTE(addr);
WriteOneByte(cTemp);
if(I2cCheckAck() == 0)
{
return 0;
}
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
I2cStart();
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
WriteOneByte(0xa1);
I2c_delay();
I2c_delay();
if(I2cCheckAck() == 0) //程序执行到这里的时候没有应答信号,直接执行 return 0 返回,前面的时序都是对的
{
return 0;
}
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
cTemp = ReadOneByte();
I2cSendNack();
I2cStop();
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
I2c_delay();
return(cTemp);
}
int main()
{
unsigned char cTemp;
I2cInit();
while(1)
{
// WriteI2cData(0x0036, 0xC8);
// WriteI2cData(0x00aa, 0x9A);
cTemp = ReadI2cData(0x0036);
}
return 0;
}
问题是:用示波器观测时序图,写EEPROM时序正常,也就是执行WriteI2cData(0x0036, 0xC8)指令时候时序是正常的,但是读I2C时(cTemp = ReadI2cData(0x0036);),写入控制字0xa1(即 WriteOneByte(0xa1); )后没有应答信号,直接执行return 0 指令返回。不知道是什么原因,SCL和SDA的上拉电阻是10k,换成4.7k、20k都试过,现象是一样的。望高手指点一二。。。