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.

Problem interfacing I2C EEPROM with TM4C launchpad



Dear all,

I have been trying to interface 24C series EEPROM with I2C1 module with TM4C launchpad with the following:

PA6 ---> SCL of EEPROM

PA7----> SDA of EEPROM

The configuration of the I2C module is done as:

SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
SysCtlDelay(10); // wastes 5 clock cycle to enable activation of the peripheral

GPIOPinConfigure(GPIO_PA6_I2C1SCL);
GPIOPinConfigure(GPIO_PA7_I2C1SDA);
SysCtlDelay(10);

GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
SysCtlDelay(10);

I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false); // have the slow mode = 100KHz
SysCtlDelay(10);

The code that has been done for writing a data to I2C Slave eeprom with Addr = 1010111 at location 0x02 inside it with the data being = 'Q' as shown below:

void I2C_SEND_CHAR()
{

I2CMasterSlaveAddrSet(I2C1_BASE, 0x57, false);
I2CMasterDataPut(I2C1_BASE, 0x02);
I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
while(I2CMasterBusBusy(I2C1_BASE))
{

// do nothing

}
I2CMasterDataPut(I2C1_BASE, 'Q');
I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

while(I2CMasterBusBusy(I2C1_BASE))
{

// do nothing

}

Now, after some time gap, I want to read back the same data from the same location of the EEPROM using the random read method of the eeprom that involves a dummy write (for setting address pointer = 0x02) and then reading the data from the location. This has been done as given below:

void I2C_RECV_CHAR()
{

I2CMasterSlaveAddrSet(I2C1_BASE, 0x57, false);
I2CMasterDataPut(I2C1_BASE, 0x02);                     // dummy write of address = 0x02
I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
while(I2CMasterBusBusy(I2C1_BASE))
{

}

I2CMasterSlaveAddrSet(I2C1_BASE, 0x57, true);
data_read = I2CMasterDataGet(I2C1_BASE);     // data_read declared as ungined int 32 bit before
I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(I2CMasterBusBusy(I2C1_BASE))
{

}
I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
while(I2CMasterBusBusy(I2C1_BASE))
{

}
}

But the problem is that I cannot read back the data from the location. It is always coming as 0xFF from the read location which is the default value written from factory. Where could be the problem? Please help

  • Your using the smaller launchpad right? not the new tm4c1294

    I belive in read you don't need the I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); since you weren't doing a receive burst, but just a single

    Also, did you use external pull-up resistors?

     

    I use this code for I2C sending just 1:

    while(I2CMasterBusy(ulI2CBase)) {}
    	
    
        //
        // Tell the master module what address it will place on the bus when
        // writing to the slave.
        //
         I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, 0);
    
        //
        // Place the command to be sent in the data register.
        //
         I2CMasterDataPut(ulI2CBase, ucReg);
    
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_START);
    
        //
        // Wait until master module is done transferring.
        //
    
    while(I2CMasterBusy(ulI2CBase)) {}
    
        //
        // Check for errors.
        //
        if( I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Place the value to be sent in the data register.
        //
         I2CMasterDataPut(ulI2CBase, ucValue);
    
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_CONT);
    
        //
        // Wait until master module is done transferring.
        //
    
    while(I2CMasterBusy(ulI2CBase)) {}
    
        //
        // Check for errors.
        //
        if( I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_FINISH);
    
        //
        // Wait until master module is done transferring.
        //
    
    while(I2CMasterBusy(ulI2CBase)) {}

     

    
    

     

  • Hi Luis,

      Thanks a lot for your reply, but im still not able to do it. Firstly, I am actually sending only one byte data to 24C02 at its address 0x02. Its not a burst. I used Burst option because single_send was not working. Secondly, I am using the small Launchpad with TM4C123H6P MCU. Thirdly, with your code, the master is getting stuck in the while(masterbusy) loop, which was not happening with my code as I have pasted. I cannot figure out whats causing the error. I have connected 2 pull up resistors (10K to 3V3) on both SDA & SCL lines.

  • You tried my code with only chaging the DataPut values and the slave address right?

    Can you please tell me in wich loop it got stuck? i used that MCU many times and never had that problem

  • Hi luis,

     Its done. Thanks for your help. i was missing out on this part in the receive code:

    I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    while(I2CMasterBusBusy(I2C1_BASE))
    {

    }

    To wind off the finish and sending the NACK to the slave. Thats why the master was busy. Thanks a lot.

    Just one more small clarification :
    What are the differences between SINGLE , BURST and BURST CONT, and QUICK COMMAND ??

    I2C_MASTER_CMD_SINGLE_SEND
    I2C_MASTER_CMD_SINGLE_RECEIVE
    I2C_MASTER_CMD_BURST_SEND_START
    I2C_MASTER_CMD_BURST_SEND_CONT
    I2C_MASTER_CMD_BURST_SEND_FINISH
    I2C_MASTER_CMD_BURST_SEND_ERROR_STOP
    I2C_MASTER_CMD_BURST_RECEIVE_START
    I2C_MASTER_CMD_BURST_RECEIVE_CONT
    I2C_MASTER_CMD_BURST_RECEIVE_FINISH
    I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP
    I2C_MASTER_CMD_QUICK_COMMAND
    I2C_MASTER_CMD_HS_MASTER_CODE_SEND

  • single is to send only byte, wich i never saw being used, because for most devices i always saw the minimum data packet to be 2 bytes, command and data, like yours.

    in receive single is used if you just need to send the command.

    Burst is just that, when you send 1 byte, you don't send the stop big, istead you keep the bus busy and keep sending data, only at the end you send the stop bit. Burst cont is to send a byte after you have done a burst_send_Start, so you don't have to send a start bit again and it also doesn't send the stop bit. burst_Send_finish is to send the last data with the stop bit