This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unusual TWI/I2C Problem

Hello

I've been experiencing an unusual problem using the TWI/I2C library for the nRF51-DK board. Basically, I found that I need to shift my device address to the left by 1-bit in order for the board and the device to communicate and I don't understand why?

The IC is an ADT7420 temperature sensor, its default address is 0x48 and its device id register is found at 0x0B. I was attempting to read this device ID to verify the operation of the chip, however the chip failed to respond unless I shifted the address to the left by 1 bit (i.e. 0x48<<1 which equals 0x90), however with a different IC (a TMP007 IR sensor) there was no problem. I decided to try shifitng the bits after looking at the SDA and SCL waveforms on an oscilloscope and they seemed out of alignment by one clock cycle. I also tested the ADT7420 with an Arduino and I had no problem with the normal address of 0x48.

I'm using the latest version of the SDK, Keil v5 and the I2C is operating at 100 kHz.

Here's a simplified section of code that I'm using:


 bool readI2cData(uint8_t address, uint8_t reg, uint8_t* data, uint8_t len)
{		
	// initialize data to zero so we don't return random values.
	for (int i = 0; i < len; i++) 
	{
		data[i] = 0;
	}
	
  // Write: register address we want to start reading from
  if (twi_master_transfer(address, &reg, 1, TWI_DONT_ISSUE_STOP))
  {
		// Read: the number of bytes requested.
    if (twi_master_transfer(address | TWI_READ_BIT, data, len, TWI_ISSUE_STOP))
    {			
      // Read succeeded.
			return true;
    }
	}
	
	// read or write failed.
  return false;
}

int main(void)
{

	

	 twi_master_init(); // Initialise I2C bus


	 while (true)
    {

		uint8_t temp_read[2];
		readI2cData(0x48<<1, 0x0B, temp_read, 2);
		
        nrf_delay_ms(100);

    }
}
  • No that's to be expected. That 0x48 is the 7-bit device address, however if you look at the code for the function you're using, twi_master_transfer() that uses the 8-bit 'address' which is the 7-bit device address followed by a '1' for read or a '0' for write. That's the address which actually goes out on the wire. That allows you to call one function for both directions of data transfer instead of calling twi_master_read() for read and twi_master_write() for write by using the last bit to figure out which direction you're going, it then shifts the address back down again and calls either *_read() or *_write().

    So that's why you need to shift the 7-bit address up by a bit before ORing it with the TWI_READ_BIT

    If you use the twi_master_read() and twi_master_write() functions, those take the 7-bit address because they already know which direction you're going in.

    So that explains why you have to shift your device address, it's because of the function you're calling. My guess would be with the TMP107 you're calling the read/write functions directly, you haven't really said exactly what you tested nor which address they are set up for, I believe that chip is configurable for 8 different addresses.

    I know nothing about arduino, but again I'm assuming that there's a read function and a write function so they take the 7-bit address, or else the function takes an address + a separate read-write flag, so again the address only needs to be the 7-bit one.

  • www.i2c-bus.org/.../

    The address is 7 bits long, followed by the direction bit. So, you need to shift the address 1 bit left, and then add the direction bit at the end. If it works without shifting the address, it is because the shifting is done in the function you are calling. twi_master_transfer() (SDK6) does not shift the address.

  • It is a sad fact of life that some manufacturers will specify I2C addresses as 0xa0 for write and 0xa1 for read, whereas others use the 7 bit form, which in that case would be 0x50. The safe way is to examine the data-sheet, where there will often be a drawing of the actual waveform/timing diagram.

Related