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.

LM4F232H5QD I2C Problem (With Microchip 24LC6 EEPROM)

Dear All,

I got a problem in i2c module 1 of Lm4f232.
In this code, I wanna write a byte data to 24LC64, and read back. Unlucky, I can't. Where is the problem within those code?? Plz help me.
( The A0, A1, A1 pins of 24LC64 is connected to GND )
( There are 2 bytes for data bytes of 24LC64)

I2C Code :

//---------------<Initial>-------------------//

 SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
 SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1);
 SysCtlPeripheralEnable( I2C1_MASTER_BASE ) ;

SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA ) ;
GPIOPinTypeI2C( GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ) ;
GPIOPinConfigure( GPIO_PA6_I2C1SCL ) ;
GPIOPinConfigure( GPIO_PA7_I2C1SDA ) ;

I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet(), false ) ;

I2CMasterEnable(I2C1_MASTER_BASE);

//---------------<Write>-------------------//

I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, false ) ;

I2CMasterDataPut( I2C1_MASTER_BASE, 0x00 ) ;
I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START ) ;
SysCtlDelay(SysCtlClockGet() / 30000);

I2CMasterDataPut( I2C1_MASTER_BASE, WRITE_ADDRESS ) ;
I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
SysCtlDelay(SysCtlClockGet() / 30000);

I2CMasterDataPut( I2C1_MASTER_BASE, DATA ) ;
I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
SysCtlDelay(SysCtlClockGet() / 30000);

I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH) ;
SysCtlDelay(SysCtlClockGet() / 30000);

//---------------<Read>-------------------//

I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, false ) ;

I2CMasterDataPut( I2C1_MASTER_BASE, 0x00 ) ;
I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START ) ;
SysCtlDelay(SysCtlClockGet() / 30000);

I2CMasterDataPut( I2C1_MASTER_BASE, WRITE_ADDRESS ) ;
I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
SysCtlDelay(SysCtlClockGet() / 30000);

I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, true ) ;
I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE ) ;
SysCtlDelay(SysCtlClockGet() / 30000);

Cnt32_2 = I2CMasterDataGet( I2C1_MASTER_BASE ) ;

 

Thanks a lot !!!

 

  • Just have a moment - travelling have just a few minutes now:

    New 4F MCU requires special treatment on this pin - change to:  SW-DRL-UG documents for you

                    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);   //   I2CSCL
                    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);   

    You don't really identify your problem - appears to me that you are sending too many bytes to the eeprom (via "put").  Also you may do better w/this method of delay post I2CMasterControl:

            while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}

  • Dear cb1_mobile,

    I add GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6); to my code, it becames

     //---------------<Initial>-------------------//
     SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
     SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1);
     SysCtlPeripheralEnable( I2C1_MASTER_BASE ) ;

     SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA ) ;
     GPIOPinTypeI2C( GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ) ;
     GPIOPinConfigure( GPIO_PA6_I2C1SCL ) ;
     GPIOPinConfigure( GPIO_PA7_I2C1SDA ) ;
     GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);

     I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet(), false ) ;

     I2CMasterEnable(I2C1_MASTER_BASE);

     

    Now, I got the wrong value of Cnt32_1, Cnt32_1 always 0xFF. Is the code still wrong in somewhere? 

    Thanks for your favor.

     

  • Sorry - have to go now - eliminate:  GPIOPinTypeI2C( GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ) ;

    Can you temporarily replace your 2 data byte eeprom with simpler, single byte one?  Also - look @ code for Atmel 2408 simple eeprom in earlier LM3S6xx and LM3S8xx folders under I2C.

    Should be able to return to this much later today - but this is all I can provide for now...

  • unlucky, the wrong value 0xff is still.

    how can I do ?

  • Dear All,

    If I programmed those code for I2C_1 initial, I always get 0xFF value of Cnt32_1 :

     
     SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
     SysCtlPeripheralEnable( I2C1_MASTER_BASE ) ;

     SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA ) ;

     GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
     GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
     GPIOPinConfigure( GPIO_PA6_I2C1SCL ) ;
     GPIOPinConfigure( GPIO_PA7_I2C1SDA ) ;

     I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet(), false ) ;

     I2CMasterEnable(I2C1_MASTER_BASE);

    Otherwise, if I change "  I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet(), false )  " to "  I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet()/400, false )   " , then I can not get any value of Cnt32_1.

  • Here's your eeprom Write Sequence diagram:  Note - 4 Bytes total sent.  EEprom adr 1010xxxW becomes 0x50 to accommodate the R/W (0) in bit 8 lsb position.  Many, many miss this.

    i2c_setup:  FOUR Byte Transfer.  Note: this code for new LM4F MCU - chose to use ROM functions rather than GPIO.  (either should work)

       
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
       
            GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);   //   I2CSCL
            ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);   
       
            ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);   
            ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);   

            ROM_I2CMasterInitExpClk(I2C1_MASTER_BASE, ROM_SysCtlClockGet(), false); 
            ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x50, false); // adr 1010 translated to 0x50.  Note R/W bit = 0 
            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x0); // 1st Byte (MSB of eeprom adr) (but the 2nd byte sent)

            // Initiate send of 2 Bytes from Master to Slave (Slave Adr & MSB of eeprom Adr)
            ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);  // generates the I2C START Condition
            while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}   //  Delay till completes

            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x0);  // 2nd Byte (LSB of eeprom adr)

            // Initiate send of 1 Byte from Master to Slave (LSB of eeprom adr)
            ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);  // NO START nor STOP Condx.
            while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}  // Delay till completes

            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0xAB);  // 3rd Byte (eeprom data for test)

            // Initiate send of 1 Byte from Master to Slave (this is dummy data for eeprom)
            ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);  // generates the I2C STOP Condition
            while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}  // Delay till completes

      
            Here's the eeprom Read Sequence Diagram:

    Note that the first portion of this Read transaction involves a WRITE to the eeprom.  The Slave Address remains 0x50 but the R/W bit switches high during the read portion.  (just post the 2nd Start Condition.)   I leave the code mechanics of this to you - nice if you report success and supply valued "verify answer" tick.

     

     

  • Assuming a 7-bit address, I think the Slave Address would remain 0x50 and the flag would change from false to true. The address 0x51 would be another EEPROM device with A2=0, A1=0, A0=1.

  • Your wording is superior to mine (that was my intent).  This I2C address scheme has challenged many - me very much among that group.   

    Have edited/corrected post - Thank you Norman - good get...  (at least this reporter claims some "points for effort")

  • Dear All,

    The code doesn't working until now. The code as below, can you check where is the problem?

    #include"hw_types.h"
    #include"hw_memmap.h"
    #include"hw_gpio.h"
    #include"hw_i2c.h"

    #include"pin_map.h"
    #include"gpio.h"
    #include"sysctl.h"
    #include"hw_ints.h"
    #include"hw_timer.h"
    #include"interrupt.h"
    #include"timer.h"
    #include"uart.h"
    #include"uartstdio.h"
    #include"i2c.h"
    #include"ssi.h"
    #include"lm4f232h5qd.h"

    void Init_Clk( void ) ;
    void Init_Timer( void ) ;
    void Timer0_ISR( void ) ;
    void Init_I2C( void ) ;

    #define  SLAVE_ADDRESS  0x50
    #define  WRITE_ADDRESS  0x01
    #define  DATA   0x88

    volatile long Cnt32_1 = 0 ;

    void Init_Clk( void )
    {
     SysCtlClockSet( SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN ) ;
    }

    void Init_Timer( void )
    {
     SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0 ) ;
     TimerConfigure( TIMER0_BASE, TIMER_CFG_PERIODIC ) ;
     TimerLoadSet(TIMER0_BASE, TIMER_A, 80000);
     TimerIntRegister( TIMER0_BASE, TIMER_A, Timer0_ISR ) ;
     TimerIntEnable( TIMER0_BASE, TIMER_TIMA_TIMEOUT ) ;
     IntEnable(INT_TIMER0A);
     TimerEnable( TIMER0_BASE, TIMER_A ) ;

    }

    void Init_I2C( void )
    {
     SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
     SysCtlPeripheralEnable( I2C1_MASTER_BASE ) ;

     SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA ) ;

     GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
     GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
     GPIOPinConfigure( GPIO_PA6_I2C1SCL ) ;
     GPIOPinConfigure( GPIO_PA7_I2C1SDA ) ;

     I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet(), false ) ;

     I2CMasterEnable(I2C1_MASTER_BASE);

     //---------------<Write>-------------------//
     I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, false ) ;

     I2CMasterDataPut( I2C1_MASTER_BASE, 0x00 ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     I2CMasterDataPut( I2C1_MASTER_BASE, WRITE_ADDRESS ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     I2CMasterDataPut( I2C1_MASTER_BASE, DATA ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     //---------------<Read>-------------------//
     I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, false ) ;

     I2CMasterDataPut( I2C1_MASTER_BASE, 0x00 ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     I2CMasterDataPut( I2C1_MASTER_BASE, WRITE_ADDRESS ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

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

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

     // Get Value
     Cnt32_1 = I2CMasterDataGet( I2C1_MASTER_BASE ) ;
    }
    void Timer0_ISR( void )
    {
     TimerIntClear( TIMER0_BASE, TIMER_TIMA_TIMEOUT ) ;
     TimerLoadSet(TIMER0_BASE, TIMER_A, 80000);

     Init_I2C( ) ;
    }
    //================================================================//

    void main( void )
    {
     Init_Clk( ) ;
     Init_Timer( ) ;
     Init_GPIO( ) ;

     while( 1 )
     {
      ;
     }
    }

    Thanks a lot.

  • Dear All,

    The code doesn't working until now. The code as below, can you check where is the problem?

    #include"hw_types.h"
    #include"hw_memmap.h"
    #include"hw_gpio.h"
    #include"hw_i2c.h"

    #include"pin_map.h"
    #include"gpio.h"
    #include"sysctl.h"
    #include"hw_ints.h"
    #include"hw_timer.h"
    #include"interrupt.h"
    #include"timer.h"
    #include"uart.h"
    #include"uartstdio.h"
    #include"i2c.h"
    #include"ssi.h"
    #include"lm4f232h5qd.h"

    void Init_Clk( void ) ;
    void Init_Timer( void ) ;
    void Timer0_ISR( void ) ;
    void Init_I2C( void ) ;

    #define  SLAVE_ADDRESS  0x50
    #define  WRITE_ADDRESS  0x01
    #define  DATA   0x88

    volatile long Cnt32_1 = 0 ;

    void Init_Clk( void )
    {
     SysCtlClockSet( SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN ) ;
    }

    void Init_Timer( void )
    {
     SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0 ) ;
     TimerConfigure( TIMER0_BASE, TIMER_CFG_PERIODIC ) ;
     TimerLoadSet(TIMER0_BASE, TIMER_A, 80000);
     TimerIntRegister( TIMER0_BASE, TIMER_A, Timer0_ISR ) ;
     TimerIntEnable( TIMER0_BASE, TIMER_TIMA_TIMEOUT ) ;
     IntEnable(INT_TIMER0A);
     TimerEnable( TIMER0_BASE, TIMER_A ) ;

    }

    void Init_I2C( void )
    {
     SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
     SysCtlPeripheralEnable( I2C1_MASTER_BASE ) ;

     SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA ) ;

     GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
     GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
     GPIOPinConfigure( GPIO_PA6_I2C1SCL ) ;
     GPIOPinConfigure( GPIO_PA7_I2C1SDA ) ;

     I2CMasterInitExpClk( I2C1_MASTER_BASE, SysCtlClockGet(), false ) ;

     I2CMasterEnable(I2C1_MASTER_BASE);

     //---------------<Write>-------------------//
     I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, false ) ;

     I2CMasterDataPut( I2C1_MASTER_BASE, 0x00 ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     I2CMasterDataPut( I2C1_MASTER_BASE, WRITE_ADDRESS ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     I2CMasterDataPut( I2C1_MASTER_BASE, DATA ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     //---------------<Read>-------------------//
     I2CMasterSlaveAddrSet( I2C1_MASTER_BASE, SLAVE_ADDRESS, false ) ;

     I2CMasterDataPut( I2C1_MASTER_BASE, 0x00 ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

     I2CMasterDataPut( I2C1_MASTER_BASE, WRITE_ADDRESS ) ;
     I2CMasterControl( I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT ) ;
     while(I2CMasterBusy(I2C1_MASTER_BASE))  {}

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

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

     // Get Value
     Cnt32_1 = I2CMasterDataGet( I2C1_MASTER_BASE ) ;
    }
    void Timer0_ISR( void )
    {
     TimerIntClear( TIMER0_BASE, TIMER_TIMA_TIMEOUT ) ;
     TimerLoadSet(TIMER0_BASE, TIMER_A, 80000);

     Init_I2C( ) ;
    }
    //================================================================//

    void main( void )
    {
     Init_Clk( ) ;
     Init_Timer( ) ;
     Init_GPIO( ) ;

     while( 1 )
     {
      ;
     }
    }

    Thanks a lot.

  • Che-Chia Li said:
    code doesn't working until now.

    Truly sorry for that.  May I register disappointment in the seeming lack of appreciation expressed?   My response was fast, detailed, illustrated and caring - perhaps deserved some small thanks. 

    Now I made the effort to download - then read your eeprom datasheet.  Stated therein is the fact that, "it takes certain real time" for the eeprom to achieve the storage of the write data.  Your "read_eeprom" code waits for the MCU to complete - but this may occur before the eeprom has fully/properly stored its data.  (by the way 0x88 is a poor choice for data - you want differing nibbles so that you can verify lsb vs msb handling - thus my suggested 0xAB)  EEprom "WP" pin never described - should tie to Gnd.

    You did a very nice job with your I2C receive coding - I've looked twice - only thing I find is the need to insert delay just before the I2C read.

    The failure report, "doesn't working" is of little value as it leaves out all detail.  Do you receive ACKs?  Do you receive a full byte?  Is that byte 0xFF instead of 0xAB?  Or has your program faulted?  Any/all of these more descriptive explanations will be of much greater aid to your forum responders - trying to assist you.

    Kindly insert pre-receive delay - see if this cures.  If not - better describe what doesn't work.  Good luck...

  • As cb1- noted, there should be a delay after each write before another operation will work. The datasheet specifies maximum of 5ms. No minimum stated. The datasheet also describes using acknowledge polling if you don't want to wait the full 5ms. That's quite a bit more involved. First must learn to crawl before walking.

    The I2C test write and read is called from within a timer ISR. Not sure if that is wise. It is usually bad practice to poll from within an ISR. Besides that, the EEPROM does have a limited number of cycles. You can wear it out. Not familiar with your platform. Hopefully your timer is low frequency.

  • Dear All,

    Thank you very very very much especially cb1 even if I don't solve this problem so far.

  • Norman Wong said:
    First must learn to crawl before walking.

      Norman - our group loves this - so true - western version is "KISS" (keep it simple...

    Our troubled I2C poster has added unwanted complications to the rather simple I2C issue - never a good idea.  The code supplied has worked @ our firm - unless I butchered "cut/paste" should work for poster too - had he not "changed the game" upon us.  Advice is to always test new/unverified code with NO outside Dependence - even if eventually needed.  As a manager we teach, "Proceed by Refinement" - Keep it Simple and gradually, controllably expand.  All at once code is ticket to frustration - for poster and lowly responders...

    Poster continues to fail to describe his error issue - adding greatly to our difficulty in diagnosis...

  • Dear All,

    After few days for taking a rest. I have solved this problem. It should be inset dealy between transmit and receive.

    BR,

    Henry

  • cb1- said:
    "it takes certain real time" for the eeprom to achieve the storage of the write data.  Your "read_eeprom" code waits for the MCU to complete - but this may occur before the eeprom has fully/properly stored its data...  Kindly insert pre-receive delay - see if this cures. 

    Re: "I have solved this problem."   Your solution appears to have other "fathers." (Norman & myself)

     BTW - this well answered post languishes on Google as, "Unverified!"   Fast/simple tick of Verified Answer surely appropriate - rewards detailed solution provider...

     

  • Hai friend,

    Please post your eeprom interface code i have problem with eeprom interface...

  • Hai,

    I am trying to interface IN1307 RTC IC and slave address is 0xD0.Please I want to know how it will change?

    Thanks,

    senthil

  • @senthil,

        It would be better to just create a new post regarding your problem.

        Also, you can review the example i2c codes at "\examples\peripherals\i2c".

    -kel