Hello there,
We had an old design where we used to read data as a I2C master device. The code was prepared to read only 1 byte, now that we have changed the I2C slave device we require to read 2 data bytes for some registers.
The writing sequence of the register address is done correctly. However, the reading sequence has some problems.
The NACK in not sent after getting the last data byte, it sends an extra byte (seen through the oscilloscope). I don't know if we are doing it correctly but we set the NACKMOD register bit to 1 just after reading the second to last byte. Here is the code of the function, any suggestion is welcome:
Int16 i2c_OEM_readX( Uint8 deviceAddr, Uint8* RegAddr, Uint8 regLen, Uint8* data, Uint8 dataLen){
Uint16 ret = 0;
Uint8 tempByte;
int i;
while(I2C_REG0->ICSTR.bit.BB); //wait for bus to be not busy
//Just send SLA+R if no register bytes to send
if(regLen !=0){
//SET BYTE COUNT (dataLen+1)
I2C_REG0->ICCNT.bit.ICDC = regLen;
I2C_REG0->ICMDR.bit.MST = 1; //make sure we're in master mode
I2C_REG0->ICMDR.bit.TRX = 1; //make sure we're in transmit mode to send register address
//set up the slave address
I2C_REG0->ICSAR.bit.SADDR = deviceAddr >> 1;
//send the START condition and the slave address
I2C_REG0->ICMDR.bit.STT = 1;
//wait for START condition and slave address to go out
waitloop(10000);
//check for a NACK
if(I2C_REG0->ICSTR.bit.NACK)
{
I2C_REG0->ICMDR.bit.STP = 1;
return(-1);
}
waitloop(2000);
//wait for transmitter to be ready then send the register address
//SEND DATA BYTES
for(i=0;i<regLen;i++){
//get the current byte
tempByte = RegAddr[i];
//wait for transmitter to be ready then send the upper byte of data
while(I2C_REG0->ICSTR.bit.ICXRDY == 0);
I2C_REG0->ICDXR.bit.D = tempByte;
//wait for data to go out
waitloop(4000);
//check for a NACK
if(I2C_REG0->ICSTR.bit.NACK){
I2C_REG0->ICMDR.bit.STP = 1;
return(-1);
}
}
}
/****************************/
//setup device for read
/****************************/
//now set up to receive the upper byte of data
I2C_REG0->ICMDR.bit.MST = 1; //make sure we're in master mode
I2C_REG0->ICMDR.bit.TRX = 0; //make sure we're in receive mode
I2C_REG0->ICMDR.bit.NACKMOD = 0; //send NACK at end
I2C_REG0->ICCNT.bit.ICDC = 0; //
//set up the slave address
I2C_REG0->ICSAR.bit.SADDR = deviceAddr >> 1;
//send the START condition and the slave address
I2C_REG0->ICMDR.bit.STT = 1;
waitloop(10000);
//check for a NACK
if(I2C_REG0->ICSTR.bit.NACK){
I2C_REG0->ICMDR.bit.STP = 1;
return(-1);
}
//Loop through and collect reads
for(i=0;i<dataLen;i++){
if(i==dataLen - 1){
I2C_REG0->ICMDR.bit.NACKMOD = 1;
}
waitloop(10000);
//wait for byte to show up in recieve buffer
while(I2C_REG0->ICSTR.bit.ICRRDY == 0);
data[dataLen-1-i] = I2C_REG0->ICDRR.bit.D;
}
I2C_REG0->ICMDR.bit.STP = 1;
}