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.

TM4C123GH6PM: I2C data register is always reading 255

Part Number:

Hi,

I have connected I2C1 with SMBUS slave. When i am trying to read data it is always giving 255. I tried changing the command code to read from different register, still data is 255.

I have connected SDA and SCL to 10k Pull-ups.

Please help me on this.

Thanks in Advance

Regards,

Tasmiya

  • Below is my code.
    void
    smbusInit(void)
    {
        //enable I2C1
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
        //wait till I2C1 is ready
        while((!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C1)))
        {
        }
        //configure I2C1 for batteries
        GPIOPinConfigure(GPIO_PA6_I2C1SCL);
        GPIOPinConfigure(GPIO_PA7_I2C1SDA);
        GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
        GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
        GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);
        I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);
        I2CMasterEnable(I2C1_BASE);
    }
    uint16_t
    systemSmbusRead(uint32_t i2cBase, uint8_t slaveAddr, uint8_t cmd)
    {
        uint8_t data[2] = {0x00,0x00};
        uint16_t rxData = 0;
        //set the slave address with write operation enabled
        I2CMasterSlaveAddrSet(i2cBase, slaveAddr, false);
        //send the address of register to write data
        I2CMasterDataPut(i2cBase, cmd);
        //set master control command to send a single byte
        I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_SEND_START);
        //wait till write is completed
        while(I2CMasterBusy(i2cBase))
         {
         }
         //set the slave address with read operation enabled
         I2CMasterSlaveAddrSet(i2cBase, slaveAddr, true);
         //wait till write is completed
          while(I2CMasterBusy(i2cBase))
          {
          }
         //set master control command to read data.
        I2CMasterControl(i2cBase, I2C_MASTER_CMD_SINGLE_RECEIVE);
        // Wait until the slave is done sending data.
         while(I2CMasterBusy(i2cBase))
         {
         }
         //read LSB data from master data register
         data[0] = I2CMasterDataGet(i2cBase);
         while(I2CMasterBusy(i2cBase))
         {
         }
         //read MSB data from master data register
         data[1] = I2CMasterDataGet(i2cBase);
         while(I2CMasterBusy(i2cBase))
         {
         }
         rxData = (data[1] << 8);
         rxData = rxData | (data[0]);
        //send the data to called function
        return (rxData);
    }
  • Greetings,

    Code shown OFTEN employs "i2cBase"!    That's incorrect! (i.e. insufficient to identify the I2C Port.)

    Earlier (higher up in listed code) the correct I2C identifier was employed.   (I2C1_BASE) placed in highlight, below)

     I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);

    That (believed mistaken) identifier occurs repeatedly - some examples follow:

     I2CMasterSlaveAddrSet(i2cBase, slaveAddr, false);

     I2CMasterDataPut(i2cBase, cmd);

     while(I2CMasterBusy(i2cBase))

    In addition - "GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);"

    (may) undo your earlier (correct) GPIOPinType() & GPIOPinConfigure().

    Always wise to check/double-check that you've correctly assigned the Slave Device's "7-bit" I2C address.

  • Hi,

    Here i2cbase refers to I2C1_BASE.

    I am passing it as an argument.

  • Thank you - I may be (especially) dull this morning - might you clarify your, "Passing as an argument?"

    We note:

    uint16_t
    systemSmbusRead(uint32_t i2cBase, uint8_t slaveAddr, uint8_t cmd)

    but can find no clear "I2C1_BASE" argument reference.   The fact that your code "started" w/the "clearer & more direct I2C1_BASE" - and then changed - invites confusion - does it not?

    As noted - do check that the Slave's (7-bit) address is correct.

    As always - a scope capture of "Activity upon SCL & SDA" greatly aids remote diagnostics...

  • Hi,

      Like what cb1 said, please provide a scope capture. Does your slave return 0xFF? Is the slave properly addressed? Does the slave ACK the command from the master?

  • Hi,

    Sorry my mistake, I had not provided the function call.

    time = systemSmbusRead(I2C1_BASE, SMARTBATTERY, VOLTAGE);

    SMARTBATTERY = 0x16

    VOLTAGE = 0x09

    I have checked in scope, i am able to see slave address .

  • Thank you - yet staff & I see little (i.e. NO) benefit from your rendering the selected I2C port unclear.

    Is the address of your slave 0x16?   We'd feel much better if you'd link to the Slave's Data.   

    Have you noted that the (actual) Slave Device's address must be Shifted Left (once) to make room for the "RS" bit?   (bit 0 which may be '1 or 0" to read or write)

    Again - scope cap (and) Slave Data Manual immensely aid diagnostics in your behalf...

  • Hi,

     I see some issues with your code. You first call      I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_SEND_START) to write to the slave. This command will hold the bus low for further command. However, you follow with the     I2CMasterControl(i2cBase, I2C_MASTER_CMD_SINGLE_RECEIVE) command. First this is a command to only read 'one' byte of data. In addition, his command will  send the start bit again. This command cannot be used to read two or more bytes. Please use the below app note to understand what commands to use in relation to bus activities. 

    Also add the highlighted in red first and then followed with wherever you have while(I2CMasterBusy(i2cBase)).

    while(!I2CMasterBusy(i2cBase))
    {
    }
    while(I2CMasterBusy(i2cBase))
    {
    }

  • Hi Charles,

    We too noted that - yet the "reduced/undefined" I2C port captured the bulk of our attention.

    Poster did note only receiving 0xFF - while we agree that the command employed was improper - would that "spoil" (even) the first byte sent from the Slave?

    We remain "in doubt" of the Slave Device's address entry...

    and WHOOPS your neat RED Highlight is NOT REQUIRED as poster's MCU is noted as TM4C123!     (which managed to 'escape' that (contrived) 'solution!')   We/smart others - hate it!

    Part Number: TM4C123GH6PM

  • Hi cb1,

      You are absolutely right that the RED highlight is not needed for TM4C123. I didn't pay attention to the part number. 

    Hi Tasmiya,

      Please ignore my last comment about adding the while(!I2CMasterBusy(i2cBase)). This is not needed for TM4C123. 

  • Thank you Charles.

    I have corrected my code, still i am receiving 255.

  • Feel your pain - yet you are "silent" regarding requests (several now) for:

    • data-sheet (manual) for your I2C Slave   (we are suspicious of your Slave Address entry)
    • the presence of the Slave's ACK - in response to your initial I2C transfer

  • Hi,

    Please find attached data sheet of slave device.

    I have received ack for initial transfer.

    NH2054SL34 spec v1.2.pdf

  • Thank you - you've now answered (both) Charles' & my team's questions.

    I've asked two of my (younger) team members to, "Search w/me for the device's Slave Address" (this after they mocked me) - even after all "23 pages of review" - we could find NO MENTION of the Slave Address!

    Did you find the Slave Address - w/in this document?    If so - might you advise where?   (page number, kindly)

    The product is similar to ones my firm produces - and the document is nicely produced - but for the "camouflage" of the Slave I2C Address.    (We keyed on this address as it is the most likely, "Cause of your Distress.")

    Note the extract (below) the cryptic "Address" is "un-noted" w/in the timing diagram.

    It is suspected that you believe the (mystery) Slave Address to be 0x16.    We musty ask - from where did you note "0x16" as the Slave Address?

    Follows a summary of Slave Commands - yet NOWHERE is "Slave Address" (i.e. the MOST CRITICAL item) clearly listed!

    *** In the (questionable) event that "0x16" is the valid, "Battery Slave Address" - then as my earlier posts noted - it (must) be shifted left once (to make room for the "R/S" bit) which results in the (new value) "0x2C" which is to be (instead) entered as the (proper) Slave Address!    Do try entering "0x2C" instead of 0x16 - and report!

  • Hi cb1,

     I'm just as curious as you what slave address was put on the bus. The poster has yet to show the scope or LA capture of the bus. I will assume he is putting out 0001_001 or 0001_010 or 0001_011 as the slave address depending what the slave device is actually is. 

  • Hi Charles,

    Staff asks, "From where did you source that "SMBus Address Listing?"

    Note that our read of his 23 pg. document revealed it to be a "Smart Battery" (almost) the equal of one's my firm produces!

    The codes you note:

    • 0001_001 denotes a Smart Charger - Not his Smart Battery   (that Battery firm produces (both) battery & charger!
    • 0001_010 we're unsure if this code is 'standard' - it is unlikely to be the Slave Address however.
    • 0001_011 as this is titled "Smart Battery" this appears the most (reasonable) Slave Address

    Now if that "0001.011x" - where x reserves the spot for placement of the I2C's R/W bit - then poster's "0x16x" WOULD signify an i2C Write - while "0x17" signifies a Read.    Should that be the case - my suggestion of the "shift Left" (creating "0x2C") would fail.

    NEVER - have any of our staff or I encountered such a "suppressed" Slave Address!   Again - from where did you source your chart?    Thanks for adding your helpful input which provides further detail - above/beyond that of poster's Smart Battery.

    *** Yet that Battery was NOT "SMART ENOUGH" to provide its Slave Address - suggest a more proper name, "Address-Less Battery!"

  • Hi cb1,

     I need to do some Google searches myself about SMbus for smart battery. I then come across this NXP app note. It seems to me that smart batteries have fixed address. 

    nxp.com/docs/en/application-note/AN4471.pdf

  • Hi, 

    I have confirmed from manufacturer of the battery for slave address. He says it is 0x16.

    Applied all sort of solutions, yet we are not able to communicate with battery.

  • Feel your (continuing) pain - yet minus an, "Instrumented Data Capture of both SDA & SCL" - your remote assistants can only rely upon a, "Line by line" examination of your code - which proves highly demanding.

    How did you confirm that an "ACK" occurred?    (you noted that earlier)

    Have you more than one "smart (yet silent) battery?"    Repetition of your result upon a "2nd victim" would likely shift the guilt from "Battery" to:

    • your implementation
    • code
    • or (extremely unlikely) "failed helper diagnostics"    (maybe)

  • Hi,

    I changed the slave address to 0x0B(0000 1011), and it worked:)

    In slave address 0001 011x, "x" did not signify the R/Wr bit. 

    Thank you.

  • That's great - good for you.

    However do note that "0x0B" (w/lsb set) is reserved for I2C "Reads."    

    To confirm - when you write to the battery - does"0x0A" succeed?   (that's my group's expectation)

    We remain "mystified" as to, "Why the battery vendor would specify "0x16x" - with that "x" being, (to our total surprise & distress)  "Without any meaning!"   Would it not have been, "Massively more effective" for the battery vendor to list the Slave Address (w/some clarity) as "0x0B to read, 0x0A" to write?

    Few posters "complete the loop" (i.e. provide a report of their solution).   You did - that's terrific & much appreciated.

    (We're going to visit several Smart Battery Specs - try to determine if (others) do a better job in providing that address...)