This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMP275 Issues (I2C)

Other Parts Discussed in Thread: TMP275, TM4C1231H6PZ, TM4C129ENCPDT

I have a TMP275 connected to a TM4C1231H6PZ, and I'm running into issues reading data from it using my own wrapper that I've written around the TivaWare I2C driver. Here's the code I'm running, and corresponding logic captures:

void Tmp275::Init() {
  // purge the I2C Buffer
  while(i2c_.I2CDataReady() > 0)
    i2c_.I2CReadChar();

  // configure the TMP275 in 12 bit mode (0.0625C resolution / 220ms)
  i2c_.I2CWrite(CONFIG_ARRAY, 2, SLAVE_ADDRESS);

  // FIXME block until the packet is sent
  SysDelayMs(10);

  // configure the TMP275 to read the temperature data register
  i2c_.I2CWrite(&TEMP_REG, 1, SLAVE_ADDRESS);
  return;
}

To initialize the TMP275, we do two things:

  • Wrte 0x60 into the configuration register, setting the sensor up for 12-bit resolution.
  • Write 0x00 into the pointer register, making future I2C reads pull from the temperature register.

Here's what a logic capture of these steps looks like:

As far as I can tell, both of these commands are working as expected, so I won't post the I2C code that the TMP275 driver is calling.

The problem arises when I actually try to read from the temperature register. Here is the TMP275 and I2C drivers that are being used:

float Tmp275::ReadTemp() {
  uint8_t buffer[2];
  i2c_.I2CReadWithoutFIFO(SLAVE_ADDRESS, 2, buffer);

  uint16_t data = (static_cast<uint16_t>(buffer[0]) << 8) | buffer[1];

  return static_cast<float>(data) * 128.0f / 32768.0f;
}

void I2CInterface::I2CReadWithoutFIFO(uint8_t slaveAddress, size_t  numberOfBytes, uint8_t* buffer) {

	if(numberOfBytes == 1) {
		buffer[0] = I2CReadWithoutFIFO(slaveAddress);
		return;
	}

	uint32_t i2cBase = I2CGiveBaseAddress(ID_);

	//Check if I2C Bus is busy
	while(I2CMasterBusBusy(i2cBase));

	//specify that we are going to read from slave device
	I2CMasterSlaveAddrSet(i2cBase, slaveAddress, true);

	// Start the I2C transaction, reading the first byte
	I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_START);
	while(I2CMasterBusBusy(i2cBase));
	buffer[0] = I2CMasterDataGet(i2cBase);

	// One byte has already been received. We can now receive the
	// rest of the bytes, not including the final byte.
	for(size_t receivedBytes = 1; receivedBytes < numberOfBytes - 1; ++receivedBytes) {
		I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
		while(I2CMasterBusBusy(i2cBase));
		buffer[receivedBytes] = I2CMasterDataGet(i2cBase);
	}

	// Receive the final byte, ending the I2C transaction.
	I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
	while(I2CMasterBusBusy(i2cBase));
	buffer[numberOfBytes - 1] = I2CMasterDataGet(i2cBase);
}

Since we're only reading 2 bytes, the loop in I2CReadWithoutFIFO(...) is skipped entirely. Here's the logic capture I get when I run this code:

Here's the relevant section of the TMP275, at least from my understanding:

Looking at the logic capture, it's pretty clear what's going wrong. The TMP275 correctly sends back the MSB of the temperature register (0x1C00 works out to 28C, which is roughly the ambient temperature where I am), but the TM4C123 sends a NAK after the first byte, ending the transaction without receiving the second byte from the TMP275.

I'm having a hard time finding examples of multi-byte I2C reads on a TM4C123, so I really don't know if the way this driver is written is appropriate. Any help with this issue would be greatly appreciated. 

  • Hello Matthew

    When the application initiates a transfer then I2CMasterBusBusy must be used in a multi master setup to see if the bus is not being used by another master or if the bus is not held by a slave. If it is not a multi master setup or bus is available, the I2C master initiates the transaction and I2CMasterBusy API should be used to detect if the operation requested with the last command request is completed before proceeding to the next command.

    Regards
    Amit
  • Hey Amit,

    Thanks for the quick response. I didn't realize there were the separate API calls, so I subbed I2CMasterBusy for I2CMasterBusBusy in between the read commands and everything worked fine.

    I'm also running identical code on a board with a TM4C129ENCPDT, and I've noticed that even with the change, I'm still receiving a NAK after the first data byte is sent back. I understand that the TM4C129 supports an I2C FIFO, but if I use the same code from above (not utilizing the FIFO) is there any reason it wouldn't work?
  • Hello Matthew,

    The I2C controller did change on the 129 device due to addition of FIFO and DMA. We saw a quirk because of the change. The controller takes time to set the Busy flag and hence if polled by the CPU earlier, it may see to the CPU that the command has been processed. If using the polling mechanism, the WA is to add a SysCtlDelay(100) before the polling is started.

    Regards
    Amit