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; }