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.


