之前一直读不出数据,设备地址对了,宏定义添加了,但就是读不出数据,调试这个花了我一天半的时间!不能忍:检查自己确实没有错误后,唯一一个需要注意的地方就是,写函数后不能立即调用读函数,因为在写需要一定时间,如果还没写完就去读那就会读取失败。
写函数需要注意跨页问题,读函数则不用,直接读就好。
关于跨页,不同芯片对应不同页数和一页的字节数,在传进来的地址需要判断是否已经另起一页,特别注意:一定要延时,留时间给上页写入完成,才能写新的一页数据。
uint8 My_I2C_Mem_Write(uint32 addr, uint8 len, uint8 *pBuf)
{
uint8 addrL = 0, addrH = 0, addrHH = 0; //KJ-
addrL = (uint8)(addr & 0xff); //KJ-
addrH = (uint8)(addr >> 8); //KJ-
addrHH = (uint8)( (i2cAddrSave & 0xFC) | ((addr >> 15) & 0x02) ); //KJ- i2cAddr | P0
//KJ- Write Start_Signal for Read
I2C_STRT();
//KJ- Write Device_Addr.
if ( I2CSTAT == mstStarted ) /* A start condition has been transmitted */
{
I2C_WRITE( addrHH & 0xFE ); //KJ- set LSB = 0 for Write
}
if ( I2CSTAT != mstAddrAckW )
{
len = 0;
}
//KJ- Write Memory_Addr
I2C_WRITE( addrH ); //KJ-
I2C_WRITE( addrL ); //KJ-
//KJ- Write Data
for (uint8 cnt = 0; cnt < len; cnt++)
{
if ((addr&0xff) == 0) //检查地址是否到达页边界,AT24CM01每页256字节,所以检测低7位是否为零即可
{
I2C_STOP();
Hal_HW_WaitUs(500);//延时等待上次写入操作完成,大概延时0.5ms,写过程需要大概0.5ms
addrL = (uint8)(addr & 0xff); //KJ-
addrH = (uint8)(addr >> 8); //KJ-
addrHH = (uint8)( (i2cAddrSave & 0xFC) | ((addr >> 15) & 0x02) ); //KJ- i2cAddr | P0
//KJ- Write Start_Signal for Read
I2C_STRT();
//KJ- Write Device_Addr.
if ( I2CSTAT == mstStarted ) /* A start condition has been transmitted */
{
I2C_WRITE( addrHH & 0xFE ); //KJ- set LSB = 0 for Write
}
if ( I2CSTAT != mstAddrAckW )
{
len = 0;
}
//KJ- Write Memory_Addr
I2C_WRITE( addrH ); //KJ-
I2C_WRITE( addrL ); //KJ-
}
I2C_WRITE(*pBuf++);
addr++;
if (I2CSTAT != mstDataAckW)
{
if (I2CSTAT == mstDataNackW)
{
len = cnt + 1;
}
else
{
len = cnt;
}
break;
}
}
//KJ- Write Stop_Signal
I2C_STOP();
return len;
}
uint8 My_I2C_Mem_Read(uint32 addr, uint8 len, uint8 *pBuf)
{
uint8 addrL = 0, addrH = 0, addrHH = 0; //KJ-
addrL = (uint8)(addr & 0xff); //KJ-
addrH = (uint8)(addr >> 8); //KJ-
addrHH = (uint8)( (i2cAddrSave & 0xFC) | ((addr >> 15) & 0x02) ); //KJ- i2cAddr | P0
//KJ- Dummy Write Start_Signal
I2C_STRT();
//KJ- Dummy Write Device_Addr.
if ( I2CSTAT == mstStarted ) // A start condition has been transmitted
{
I2C_WRITE( addrHH & 0xFE ); //KJ- set LSB = 0 for Write
}
if ( I2CSTAT != mstAddrAckW )
{
len = 0;
}
//KJ- Dummy Write Memory_Addr
I2C_WRITE(addrH); //KJ-
I2C_WRITE(addrL); //KJ-
//KJ- Dummy Write Stop_Signal
I2C_STOP();
//KJ- Write Start_Signal for Read
I2C_STRT();
if ( I2CSTAT == mstStarted ) // A start condition has been transmitted
{
I2C_WRITE( addrHH | 0x01 ); //KJ- set LSB = 1 for Read
}
if ( I2CSTAT != mstAddrAckR )
{
len = 0;
}
// All bytes are ACK'd except for the last one which is NACK'd. If only
// 1 byte is being read, a single NACK will be sent. Thus, we only want
// to enable ACK if more than 1 byte is going to be read.
if (len > 1)
{
I2C_SET_ACK();
}
for (uint8 cnt = 0; cnt < len; cnt++)
{
// slave devices require NACK to be sent after reading last byte
if (cnt == len-1)
{
I2C_SET_NACK();
}
I2C_READ(*pBuf++); // read a byte from the I2C interface
if (I2CSTAT != mstDataAckR)
{
if (I2CSTAT == mstDataNackR)
{
len = cnt + 1;
}
else
{
len = cnt; // something went wrong, so don't count last byte
}
break;
}
}
I2C_STOP();
return len;
}
/**************************延时函数********************************************/
void Hal_HW_WaitUs(uint16 microSecs)
{
while(microSecs--)
{
/* 32 NOPs == 1 usecs */
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop");
}
}