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 problem when switching system to clock to 80 MHz

Part Number: TM4C123GH6PM

Hi,

The values I get when using I2C with system clock set to SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ); works fine, but when I increase the system clock to 80 MHz communication still exists, but values are way off. Doesn't make sense to me as I though the clock speed for the I2C clock line would still be set to 100 kbps.


SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//Set clock to 80 MHz
//initialize I2C module 0
void InitI2C0(void)
{
    //enable I2C module 0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

    //reset module
    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);

    //enable GPIO peripheral that contains I2C 0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    // Configure the pin muxing for I2C0 functions on port B2 and B3.
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    // Select the I2C function for these pins.
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

    // Enable and initialize the I2C0 master module.  Use the system clock for
    // the I2C0 module.  The last parameter sets the I2C data transfer rate.
    // If false the data rate is set to 100kbps and if true the data rate will
    // be set to 400kbps.
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet() , false);

}


//read specified register on slave device
uint8_t I2CReceive(uint8_t slave_addr, uint8_t reg)
{
    while(I2CMasterBusy(I2C0_BASE));
    //specify that we are writing (a register address) to the
    //slave device
    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false);

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

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

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

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

    //send control byte and read from the register we
    //specified
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

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

    //return data pulled from the specified register
    return I2CMasterDataGet(I2C0_BASE);
}



void I2C_SEND(uint8_t slave_addr, uint8_t reg, uint8_t data)
{
    while(I2CMasterBusy(I2C0_BASE));
    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false);

    //Send register address on slave device
    I2CMasterDataPut(I2C0_BASE, reg);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(I2CMasterBusy(I2C0_BASE));
    I2CMasterDataPut(I2C0_BASE, data);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH );
    while(I2CMasterBusy(I2C0_BASE));

}

  • Jacob Smith said:
    The values I get when using I2C with system clock set to SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ); works fine

    May I strongly disagree?      The parameter in "highlight" is improper - would severely  "Overclock"  the MCU - thus proves "ILLEGAL!"     You can descend to  NO LOWER than  "SYSDIV_2.5" - when the  "SYSCTL_USE_PLL"  parameter is "in play."   Thus - your claim of,  "working fine"  is subject to HIGH dispute.

    Jacob Smith said:
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//Set clock to 80 MHz

    You've "Nailed this Setting" - that's perfect for your desired 80MHz.

    You state only that the values are,  "Way off" - such does not prove "quantitatively valuable" for remote diagnosis.     And - does it not  seem strange - that your ILLEGAL System Clock Setting - is reported to work - while your LEGAL/CORRECT Setting - Fails?

    Diagnosing any of the Serial Bus implementations - most always - demands a scope.    This enables the confirmation of  "Bit Rate" as well as enabling the studied view of multi-byte, serial transactions.

    There is no mention of your use of,  "External pull-up resistors" (~10K) upon each of the two I2C lines.    (internal ones are "unduly high" in value - lead to "rounded edges" and invite signal reflection.)

    Often "Single Stepping your code" - while observing each result - will identify "just where" your code or connection is "breaking."

  • That is very weird then because it does work absolutely fine with the invalid clock setting. I have been running the program with the "invalid" clock for a while now. It does work just fine with the "invalid" clock setting. I have grabbed a lot of correct data from the sensor and everything was working fine until I switched the clock to run at 80 MHz.
  • Indeed - I DO ... "Feel your pain."    Understand - I could not let you (continue) to Illegally operate the MCU - which could cause harm - due to "over-dissipation" brought on by a "too-high" system clock setting!

    You are "silent" with regard to: (wrt)

    • presence of external pull up Rs
    • presence of scope
    • outcome from suggested,  "Single Stepping"  

    Diagnostics is one of my firm's thrusts - I would suggest that you "dial down" your system clock - experience teaches that this often proves helpful.

    • Changing to  "Sys_Div_4" will yield a 50MHz SysClk  
    • Changing to  "Sys_Div_5" will yield a 40MHz SysClk.    

    I believe that (one or both) of these (lowered frequencies) - has a better chance of success.   (than 80MHz ... it WILL require a scope to "pinpoint WHY?")

  • Funny you should mention trying it at 50 MHz and 40 MHz because that is exactly what I did before I read your reply. Yes, it works at 40 MHz, and 50 MHz, but not at 66 MHz or 80. I will have to wait to Monday for scope. The sensor is on a breakout board which does have pull up R's on it. Will single step through and see what I can find.

    Thanks
  • Perhaps NOT so funny - some may claim, "Inspired."     Might you award that "fix" with its earned,  "This Resolved my Issue"  click-box?

    When you gain  "scope access"  you can,  "Ease the measurement of the bit rate" - by setting data to:  "0x55  or  0xAA" - either of which emits an alternating "bit pattern" - very easy to verify & measure...

    Unstated is:

    • How you are powering your I2C Slave  (and have you measured that voltage - WHILE an I2C transaction is,  "On the Wire?"
    • The "separation distance AND cable or wire length" between your MCU and the (assumed) Slave Board.    I2C IS a short-length interface - the shorter the better.

    When you "illegally" chose "Sys_Div_1" as a parameter - the System Clock "over-flowed" - and we "Quick Calculated" your (actual) frequency as  "One of those two."     (thus you received TWO frequencies - for the price of just ONE!)     Which SO deserves the "This Resolved" clicking...

  • Thank you - thank you very much.

    If/when you can access a scope - and observe the I2C bit rate (eased via the selection of 0x55/0xAA to excite "SDA") - as well as a 2-3 byte,  "I2C transaction" - we can "delve deeper."

    One thing to,  "Keep in mind"  - good as the '123 is it enforces "wait states" when the System Clock exceeds (40 or 50MHz,  MCU Manual should detail) and (this) may disrupt the I2C clocking.    Dialing down your System clock - as was directed - eliminated that "issue" from our,  "Suspect List."      (there remain (other) unsavory characters - likely lurking - just "out of sight.")