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.

TM4C1294NCPDT: How to read multiple bytes from I2C register?

Part Number: TM4C1294NCPDT

I have no trouble reading a single byte from a register on I2C device, but my following problem obviously has some bug when reading 2 bytes. Could anyone give me a pointer? Thanks!

int I2CReceive(uint32_t slave_chn, uint8_t reg, uint8_t num_of_args)
{
int iTemp;

//specify that we are writing (a register address) to the slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, false);

//specify register to be read
I2CMasterDataPut(I2C2_BASE, reg);

//send control byte and register address byte to slave device
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);

//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));

//SysCtlDelay(6000);
//specify that we are going to read from slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);

if (num_of_args==1){

//This section works!
//send control byte and read from the register we
//specified
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));

//return data pulled from the specified register
return (short)I2CMasterDataGet(I2C2_BASE);


}
else{

//num_of_args==2, this won't work
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));

//return data pulled from the specified register
iTemp= I2CMasterDataGet(I2C2_BASE);

I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));

//return data pulled from the specified register
iTemp= iTemp| I2CMasterDataGet(I2C2_BASE)<<8;

return iTemp;


}

}

  • I don't see your call to "I2CMasterBurstLengthSet(I2C2_BASE, 2);". You need to set the burst length before doing a burst transfer.
  • I took your suggestion and still have problem

    From the logic analyzer, I expect 4 bytes on the bus in a group, but often the master refuses the ACK often, so I see 2 or 3-byte groups

    _____________

    int I2CReceiveWord(uint32_t slave_chn, uint8_t reg)
    {
    int iTemp;

    //specify that we are writing (a register address) to the slave device
    I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, false);

    //specify register to be read
    I2CMasterDataPut(I2C2_BASE, reg);

    //send control byte and register address byte to slave device
    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //specify that we are going to read from slave device
    I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);

    I2CMasterBurstLengthSet(I2C2_BASE, 2);
    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //return data pulled from the specified register
    iTemp= I2CMasterDataGet(I2C2_BASE);

    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //return data pulled from the specified register
    iTemp= iTemp| I2CMasterDataGet(I2C2_BASE)<<8;


    return iTemp;

    }

  • I2C is new to me, do we need to use burst mode at all? I just need to read two bytes from a register (I need to read Temperature from Microchip's MCP9600, see timing below)

     I2C is new to me, do we need to use burst mode at all? I just need to read two bytes from a register (I need to read Temperature from Microchip's MCP9600)

  • It looks to me like the MCP9600 requires burst mode to read all 16 bits of the temperature registers. Can you compare what you see on the logic analyzer to figure 4-3 of the Microchip datasheet? Where does it differ?
  • Attached is a screen shot, and you can see the master (TM1294) refused to ACK the first byte read from the device, the X marks the place the master should ACK at this point

    BTW, I separate the read routine to make it a little easier to read:

    //read specified register on slave device
    int I2CReceiveWord(uint32_t slave_chn, uint8_t reg)
    {
    int iTemp;

    //specify that we are going to read from slave device

    I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);

    I2CMasterBurstLengthSet(I2C2_BASE, 2);
    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //return data pulled from the specified register
    iTemp= I2CMasterDataGet(I2C2_BASE);

    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //return data pulled from the specified register
    iTemp= iTemp| I2CMasterDataGet(I2C2_BASE)<<8;


    return iTemp;


    }

  • It seems we need to use I2C_MASTER_CMD_BURST_RECEIVE_CONT to get the second byte. I will take a closer look
  • After I use I2C_MASTER_CMD_BURST_RECEIVE_CONT (see codes attached), at least the master will ACK the second byte.

    but new problem shows up

    For the above capture, we can see the second byte is 0x01 and the third byte is 0x89, which matches the readings from MCP9600

    When I exam the readings from  I2CReceiveWord, I found out the first byte is 0x88 and the second byte 0x1, and I have no clue what they are

    Even the attempt to flush FIFO by calling I2CMasterDataGet eight times first won't help, the data is unpredictable (but the output from MCP9600 looks perfectly fine). Any pointer?

    int I2CReceiveWord(uint32_t slave_chn, uint8_t reg)
    {
    int iTemp;
    int i, i1, i2, i3;

    //specify that we are writing (a register address) to the
    //slave device
    //I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, false);

    //specify register to be read
    //I2CMasterDataPut(I2C2_BASE, reg);

    //send control byte and register address byte to slave device
    //I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    //wait for MCU to finish transaction
    //while ((I2CMasterBusy(I2C2_BASE)));

    //for (i=0; i<8; i++) I2CMasterDataGet(I2C2_BASE); //Do we need to flush the FIFO?

    ///SysCtlDelay(6000);
    //specify that we are going to read from slave device
    I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);

    I2CMasterBurstLengthSet(I2C2_BASE, 2);
    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //return data pulled from the specified register
    i1= I2CMasterDataGet(I2C2_BASE);
    iTemp=(i1&0xff)<<8;

    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C2_BASE));

    //return data pulled from the specified register
    i2=I2CMasterDataGet(I2C2_BASE);
    iTemp= iTemp| (i2&0xff);

    while(I2CMasterBusy(I2C2_BASE));


    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    if (iTemp==257){
    iTemp=-1;
    }

    return iTemp;


    }

  • Per Amit Ashara's suggestion, www.ti.com/.../spma073.pdf helped me to get it going again