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 EEPROM 24LC64

Other Parts Discussed in Thread: TM4C123GH6PM, EK-TM4C1294XL

Hi

Here is my code for enable, write and read a byte to the EEPROM 24LC64 on I2C from the TM4C123GH6PM micro:

For some reason I fail to write and read the eeprom memory.

Please give me a hint.

#define SLAVE_ADDRESS 0xA0

void I2C_Init() {

    // Set the clocking
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

    // The I2C0 peripheral must be enabled before use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);

    //I2C0 is used with PortB[3:2].
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlDelay(10000);

    // Select the I2C function for these pins.  This function will also
    // configure the GPIO pins pins for I2C operation, setting them to
    // open-drain operation with weak pull-ups.
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

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

    // 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.  For this example we will use a data rate of 100kbps.
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
    SysCtlDelay(10000);  // delay mandatory here - otherwise portion of SlaveAddrSet() lost!

    //Reconfigure for correct operation
    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);

    //I2C0_BASE
    I2CMasterEnable(I2C0_BASE);
}


void eepromWrite(uint16_t address_u16, uint8_t data_u8)
{
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
    while(I2CMasterBusy(I2C0_BASE))  {}

    I2CMasterDataPut(I2C0_BASE, 0x00); //WRITE
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(I2CMasterBusy(I2C0_BASE))  {}

    I2CMasterDataPut(I2C0_BASE, address_u16); //ADDRESS
    I2CMasterControl(I2C0_BASE,  I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE))  {}

    I2CMasterDataPut(I2C0_BASE, data_u8);    //DATA
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(I2CMasterBusy(I2C0_BASE))  {}
}


void eepromRead(uint16_t address_u16, uint32_t *rxdata_pu8, uint32_t rxdataLen_u32)
{
    uint32_t ret = 0;

    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
    while(I2CMasterBusy(I2C0_BASE))  {}

    I2CMasterDataPut(I2C0_BASE, 0x00);    //READ
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(I2CMasterBusy(I2C0_BASE))  {}

    I2CMasterDataPut(I2C0_BASE, address_u16); //ADDRESS
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE))  {}



    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
    while(I2CMasterBusy(I2C0_BASE))  {}

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE );
    while(I2CMasterBusy(I2C0_BASE))  {}

    ret = I2CMasterDataGet(I2C0_BASE) & 0xFF;
    rxdata_pu8[0] = ret;
}

int main() {

    uint8_t tx;
    tx = 0x99;
    uint32_t rx[1];

    I2C_Init();
    while (1){

        eepromWrite(0x0, tx);

        SimpleDelay();

        rx[0] = 0x0;
        eepromRead(0x0, rx, 1);


        printf("Tx=%X Rx=%X / ", tx, rx[0]);
    }

}

Thank You.

Regards.

  • liv lov said:
    //Reconfigure for correct operation
        GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
        GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);

    Much (most) of the code you list here sprang from my years' past I2C post here for (LX4F/TM4C) - but for that "new" Reconfigure you've added.  Note - I've not fully reviewed that long code dump - but quickly noted the "reconfigure."

    As many posters past noted - code I listed (minus that reconfigure) was confirmed - and continues to work, today.  Your reconfigure (and any other changes) - perhaps not so much...

    As always - I2C works best when external pull-up Rs (4K7-10K) are alive/well - each I2C signal line.

  • I don't understand this:

    As always - I2C works best when external pull-up Rs (4K7-10K) are alive/well - each I2C signal line.

     

    I am more interested in the write and read functions.

    I am not sure I have correctly implemented the read and write steps....

  • Does anybody having an answer?

    I wrote the exact same type of code WRITE control byte and  4 data bytes and in debug it works but full speed it misses byte [1], [2]. control byte and [0] are okay and the last byte [3] too

    this smell a bit fishy any help on the HW I2C unit?

    my code:

        I2CMasterSlaveAddrSet(I2C2_BASE, I2CEE_MACH_ADDRESS, false);

        blk_byte_size = 2;

        trxblock[0] = 10;//(EE_addr >>8) & 0xFF;        // higher byte
        trxblock[1] = 11;//EE_addr         & 0xFF;        // lower byte
        trxblock[2] = 12;//*data & 0xFF;                // TX data byte
        trxblock[3] = 13;//(*data & 0xFF)+1;                // TX data byte

        I2CMasterDataPut(I2C2_BASE, trxblock[0]);

        I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START);    //send Start, send8

        if(I2CMasterErr(I2C2_BASE) == I2C_MASTER_ERR_ADDR_ACK);    // if EEPROM still flashing page ACK is not given
        {
            UARTprintf("tx nACK\n");
        }

        while(I2CMasterBusy(I2C2_BASE));

        for(tx_cnt=1;tx_cnt< 2 +blk_byte_size -1; tx_cnt++)    //<2 due to addr, skip [0] and stop before last
        {
            I2CMasterDataPut(I2C2_BASE, trxblock[tx_cnt]);

            I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);    // send8

            while(I2CMasterBusy(I2C2_BASE));

        }

        I2CMasterDataPut(I2C2_BASE, trxblock[tx_cnt]);

        I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);    //    send8 and Send stop
      
        if(I2CMasterErr(I2C2_BASE) != 0)
        {
            UARTprintf("failed EE date write\n");
            return 1;

        }
        delay_ms(10L);    // EEPROM page write delay


  • Hello Thomas

    Is this on TM4C123 device? Can you add a SysCtlDelay(1000) before the while(I2CMasterBusy(I2C2_BASE)) check

    Also I do see some issues in your code especially the check for ACK

    Regards
    Amit
  • Thomas Durrer said:
    in debug it works but full speed it misses byte [1], [2]

    Looking quickly I noted those "UARTprintf()" (usually) deadly to any "timed serial" transfer.

    But now - those printf only occur during error condition - thus escape blame.

    What is the separation between your MCU and remote, I2C target - and is the interconnect cable/wiring suitable for that distance & transfer speed?   Are your pull-up R's (perhaps) mismarked - or too high in value?    Do capacitors appear either I2C line?

    As always scope view of data @ MCU and at Slave provides great value.

    From your report you appear on a, "ragged timing edge" - that's not (especially) fishy...   (nor tasty...)

  • Gentlemen

    Thank you for your suggestions, I got it working.

    I added a SysCtlDelay(1000) before the while(I2CMasterBusy(I2C2_BASE)) and it works wonder!

    I read and write now an entire page of 128bytes to the EEPROM using 100kbit by HW peripherals

    btw I use TM4C1294KPCDT, similar to the Launchpad Tiva EK-TM4C1294XL the EEPROM is external and is a Micro Chip 24FC1024

  • Hello Thomas,

    As suspected the device was TM4C129 which has an issue where the Busy Status for the controller does not get set immediately but only after some time. So it is possible that it may skip the next set of bytes till the Busy Status does get set.

    Regards
    Amit