Problem to communicate between EEPROM M24C04 and LPC11C24

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Problem to communicate between EEPROM M24C04 and LPC11C24

1,675 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Fri Sep 12 00:50:42 MST 2014
Hello,

I want to connect an EEPROM M24C04 on my chip LPC11C24, but I meet some problems. The most significant, the clock on the SCL port seems doesn't work, cause I didn't have impulsion on the scopemeter. This is my program :
/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/
static volatile uint32_t ticks = 0;
static volatile int32_t Ret = I2C_OK;
/*****************************************************************************
 * Define EEPROM
 ****************************************************************************/

#define DEFAULT_I2C    I2C0
#define I2C_DEFAULT_SPEED    400000
#define DATA_SIZE       6
#define I2C_SLAVE_EEPROM_ADDR       0x50
#define BYTE_ADDR       0x00

/* Data area for slave operations */
static uint8_t sendData[DATA_SIZE] = {BYTE_ADDR,0x48,0x45,0x4c,0x4c,0x4f}; //Byte d'addresse + "HELLO"
static uint8_t receiveData[DATA_SIZE];

/* Xfer structure for slave operations */
static I2C_M_SETUP_Type TransferCfg;

/*****************************************************************************
 * Private functions
 ****************************************************************************/
/********************************************************************//**
 * @brief        Send a byte
 * @param[in]    databyte: number of byte
 * @return       None
 *********************************************************************/
static void I2C_SendByte ( uint8_t databyte, Bool ack)
{
/* Write data to DAT */
LPC_I2C->DAT = databyte & I2C_I2DAT_BITMASK;

if (ack)
{
/* Set AA bit */
LPC_I2C->CONSET = I2C_I2CONSET_AA;
/* Clear the SI flag */
LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
}
else
{
/* Set STO and AA bits */
LPC_I2C->CONSET = I2C_I2CONSET_AA|I2C_I2CONSET_STO;
/* Clear the SI flag */
LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
}
}

/********************************************************************//**
 * @brief        Get a byte
 * @param[out]   retdat    pointer to return data
 * @param[in]    ack        assert acknowledge or not, should be: TRUE/FALSE
 * @return       None
 *********************************************************************/
static void I2C_GetByte (uint8_t *retdat, Bool ack)
{
    *retdat = (uint8_t) (LPC_I2C->DAT & I2C_I2DAT_BITMASK);

    if (ack)
    {
        LPC_I2C->CONSET = I2C_I2CONSET_AA;
        LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
    }
    else
    {
        LPC_I2C->CONCLR = I2C_I2CONCLR_AAC|I2C_I2CONCLR_SIC;
     }
}

/********************************************************************//**
 * @brief       Wait for interupt
 * @param[in]    timeout  timeout value
 * @return       None
 *********************************************************************/
/*********************************************************************//**
 * @brief       Reset I2C Block
* @param[in]    None
 * @return      None
 **********************************************************************/

__INLINE void I2C_Reset(void)
{
/* Reset STA, STO, SI */
LPC_I2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA;

    /* Enable Slave I2C operation */
    LPC_I2C->CONSET = I2C_I2CONSET_I2EN;
}

static __INLINE void I2C_WaitInt(uint32_t timeout)
{
    uint32_t tm = timeout;
    // Wait for sending ends
    while ((!(LPC_I2C->CONSET & I2C_I2CONSET_SI)) && tm )
    {
        tm--;
    }
}

static void Init_I2C_PinMux(void)
{
Chip_IOCON_PinMuxSet(LPC_IOCON, IOCON_PIO0_4, IOCON_FUNC1 | IOCON_SFI2C_EN);
Chip_IOCON_PinMuxSet(LPC_IOCON, IOCON_PIO0_5, IOCON_FUNC1 | IOCON_SFI2C_EN);
}

/* Initialize the I2C bus */
static void I2C_Init(I2C_ID_T id, int speed)
{
/* Select port function */
Init_I2C_PinMux();

uint32_t temp;
#if 1
LPC_SYSCTL->PRESETCTRL |= (0x1<<1);
    #else
LPC_SYSCTL->PRESETCTRL |= (0x1<<0);
#endif
//Enable clock
LPC_SYSCTL->SYSAHBCLKCTRL |= (1 << SYSCTL_CLOCK_I2C);

/* Set clock rate */
temp = SystemCoreClock / speed;
I2C_DEV->SCLH = (uint32_t)(temp/2);
I2C_DEV->SCLL = (uint32_t)(temp - I2C_DEV->SCLH);

/* Initialize I2C Interrupt */
NVIC_EnableIRQ(I2C0_IRQn);
NVIC_SetPriority(I2C0_IRQn, 0);

/* Set I2C operation to default */
I2C_DEV->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);

I2C_Reset();
}

/*****************************************************************************
 * Public functions
 ****************************************************************************/


/********************************************************
 * Generate a start condition on I2C bus
 ********************************************************/
void I2C_Start (void)
{
    volatile uint32_t timeout = 0;

restart:
    timeout = 0;
    // Enter to Master Mode
    LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
    LPC_I2C->CONSET = I2C_I2CONSET_STA;

     // Wait for complete
   /* while(1)
    {
        if((LPC_I2C->STAT == I2C_I2STAT_M_TX_START) ||(LPC_I2C->STAT == I2C_I2STAT_M_TX_RESTART))
            break;

        timeout++;
        if(timeout > 0x1000)
        {
            I2C_Reset();
            goto restart;
        }
    }*/
}

/********************************************************
 * Generate a stop condition on I2C bus
 ********************************************************/
void I2C_Stop (void)
{
/* Set STO and AA bits */
LPC_I2C->CONSET = I2C_I2CONSET_AA|I2C_I2CONSET_STO;
/* Clear the SI flag */
LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;

while(LPC_I2C->CONSET & I2C_I2CONSET_STO)
    {
        if(LPC_I2C->CONSET & I2C_I2CONSET_SI)
            LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
    }
}
/*********************************************************************//**
 * @brief        Handle I2C Master states.
 * @param[in]    CodeStatus    I2C state
 * @param[in]    TransferCfg   Pointer to a I2C_S_SETUP_Type structure that
 *                                 contains specified information about the
 *                                 configuration for master transfer.
 * @return       It can be
 *                - I2C_OK
 *                - I2C_BYTE_RECV
 *                - I2C_BYTE_SENT
 *                - I2C_SEND_END
 *                - I2C_RECV_END
 *                - I2C_ERR
 *                - I2C_NAK_RECV
 **********************************************************************/
int32_t I2C_MasterHanleStates(uint32_t PreStatus,uint32_t CodeStatus, I2C_M_SETUP_Type *TransferCfg)
{
    uint8_t tmp;
    switch(CodeStatus)
    {
        case 0x08: /*!< A start condition has been transmitted */
        case 0X10: /*!< A repeat start condition has been transmitted */
            // Send data first
            if(TransferCfg->tx_count < TransferCfg->tx_length)
            {
                /* Send slave address + WR direction bit = 0 */
                I2C_SendByte((TransferCfg->sl_addr7bit << 1), TRUE);
            }
            else
            {
                /* Send slave address + RD direction bit = 1 */
                I2C_SendByte(((TransferCfg->sl_addr7bit << 1) | 0x01), TRUE);
            }
            // Initialize Master data counter
            TransferCfg->tx_count == 0;
            // Clear STA bit
            LPC_I2C->CONCLR = I2C_I2CONCLR_STAC;
            return I2C_BYTE_SENT;

        case 0x18: /*!< SLA+W has been transmitted, ACK has been received */
        case 0x28:  /*!< Data has been transmitted, ACK has been received */
        /* Load DAT with next data byte from Master Transmit buffer*/
        /* Increment the Master data counter*/
        /* Increment Master Transmit buffer pointer*/
        if(TransferCfg->tx_count > (TransferCfg->tx_length - 2))
            {
                I2C_SendByte(TransferCfg->tx_data[TransferCfg->tx_count++], FALSE); // the next byte is the last byte, send STOP
                return I2C_SEND_END;
            }
        else
        {
        I2C_SendByte(TransferCfg->tx_data[TransferCfg->tx_count++], TRUE);
        return I2C_BYTE_SENT;

        }

        case 0x30: /*!< Data has been transmitted, NACK has been received */
        I2C_Stop();
            if(TransferCfg->tx_count < TransferCfg->tx_length)
            {
                I2C_Start();
                return I2C_OK;
            }
            else
                return I2C_SEND_END;

        case 0x40: /*!< SLA+R has been transmitted, ACK has been received */
        LPC_I2C->CONSET = I2C_I2CONSET_AA;
            LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
            return I2C_BYTE_RECV;

        case 0x50: /*!< Data has been received, ACK has been returned */
        case 0x58: /*!< Data has been received, NACK has been returned */
            if (TransferCfg->rx_length)
            {
                if(TransferCfg->rx_count >= TransferCfg->rx_length)
                    return I2C_RECV_END;
                if((TransferCfg->rx_length == 1)||(TransferCfg->rx_count > (TransferCfg->rx_length - 2)) )
                {
                    I2C_GetByte( &tmp, FALSE);    // the next byte is the last byte, send NACK
                }
                else
                {
                    I2C_GetByte( &tmp, TRUE);

                }
                TransferCfg->rx_data[TransferCfg->rx_count++] = tmp;
                if(TransferCfg->rx_count >= TransferCfg->rx_length)
                    return I2C_RECV_END;
            }
            else
            {
                if(TransferCfg->tx_count < TransferCfg->tx_length)
                    I2C_Start();
                else
                    return I2C_SEND_END;
            }
            return I2C_BYTE_RECV;

        case 0x48: /*!< SLA+R has been transmitted, NACK has been received */
        case 0x20: /*!< SLA+W has been transmitted, NACK has been received */
        I2C_Stop();
            return I2C_ERR;

        case 0x38: /*!< Arbitration lost in SLA+R/W or Data bytes */
            if(TransferCfg->tx_count < TransferCfg->tx_length)
                I2C_Start();
            else
                return I2C_SEND_END;
            return I2C_OK;

        /*case I2C_I2STAT_S_RX_ARB_LOST_M_SLA: //!< Arbitration lost in SLA+R/W as master
        case I2C_I2STAT_S_RX_ARB_LOST_M_GENCALL: //!< Arbitration lost in SLA+R/W (GENERAL CALL) as master
            I2C_Stop();
            I2C_Start();
            return I2C_BYTE_RECV;*/

        case I2C_I2STAT_BUS_ERROR: /*!< Bus Error */
        /* Set STO and AA bits */
        LPC_I2C->CONSET = I2C_I2CONSET_AA|I2C_I2CONSET_STO;
        /* Clear the SI flag */
        LPC_I2C->CONCLR = I2C_I2CONCLR_SIC;
            if((TransferCfg->tx_count <= TransferCfg->tx_length)||(TransferCfg->rx_count < TransferCfg->rx_length))
            {
                I2C_Start();
                if((PreStatus == I2C_BYTE_SENT)&& TransferCfg->tx_count)     // sending failed
                {
                    TransferCfg->tx_count--;
                }
            }
            return I2C_OK;

        case I2C_I2STAT_NO_INF: /*!< No relevant information */
        default:
              return I2C_OK;
    }
}

/*********************************************************************//**
 * @brief         Transmit and Receive data in master mode
 * @param[in]    TransferCfg        Pointer to a I2C_M_SETUP_Type structure that
 *                                 contains specified information about the
 *                                 configuration for master transfer.
 * @return         SUCCESS or ERROR
 *
 * Note:
 * - In case of using I2C to transmit data only, either transmit length set to 0
 * or transmit data pointer set to NULL.
 * - In case of using I2C to receive data only, either receive length set to 0
 * or receive data pointer set to NULL.
 * - In case of using I2C to transmit followed by receive data, transmit length,
 * transmit data pointer, receive length and receive data pointer should be set
 * corresponding.
 **********************************************************************/
void I2C_MasterTransmitData(I2C_ID_T id, I2C_M_SETUP_Type *TransferCfg)
{
    const uint32_t timeout_max = 0x1000;
    uint32_t timeout = 0x100000;
    uint32_t flag= 0;

    // Reset I2C setup value to default state
    TransferCfg->sl_addr7bit = I2C_SLAVE_EEPROM_ADDR;

    TransferCfg->rx_data = NULL;
    TransferCfg->rx_length = 0;

    TransferCfg->tx_data = sendData;
    TransferCfg->tx_length = DATA_SIZE;

    TransferCfg->retransmissions_count = 0;
    TransferCfg->tx_count = 0;
    TransferCfg->rx_count = 0;

    /* First Start condition*/
    I2C_Start();

    while(flag != 1)
    {
        if( Ret & (I2C_BYTE_SENT|I2C_BYTE_RECV))
        {
            I2C_WaitInt(timeout_max);
            timeout = timeout_max;
            if(!(LPC_I2C->CONSET & I2C_I2CONSET_SI))
            {
            flag = 0;
            }
        }
        else if ((Ret & I2C_SEND_END) || (Ret & I2C_RECV_END))// If no need to wait for data from Slave// If no need to wait for data from Slave
        {
            if((TransferCfg->tx_count >= TransferCfg->tx_length) && (TransferCfg->rx_count >= TransferCfg->rx_length))
            {
            flag = 1;
            }
        }
        else if (I2C_CheckError(Ret))
        {
            if(I2C_CheckError(Ret) || (timeout == 0))
            {
                if (++TransferCfg->retransmissions_count > TransferCfg->retransmissions_max)
                {
                flag = 0;
                }
                I2C_Start();
                timeout = timeout_max;
            }
        }
    }
}

void SysTick_Handler(void)
{
ticks++;
}

void I2C_IRQHandler(void)
{
Ret = I2C_MasterHanleStates(Ret, LPC_I2C->STAT & I2C_STAT_CODE_BITMASK, &TransferCfg);
}

/**
 * @briefMain program body
 * @returnint
 */
int main(void)
{
SystemCoreClockUpdate();
Board_Init();
I2C_Init(I2C0, I2C_DEFAULT_SPEED);
I2C_MasterTransmitData(I2C0, &TransferCfg);

return 0;
}


Thank you for your help.
Regard.
0 Kudos
25 Replies

1,449 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by serge on Fri Sep 19 05:51:55 MST 2014
Maybe your EEPROM is defective?
0 Kudos

1,449 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Wed Sep 17 05:16:09 MST 2014
New clue, In fact I can see impulsion on SDA and SCL output of lpc11c24 only if SCL is not connected to the input SCL of EEPROM. When I connect it, SDA and SCL state become high and stay high, weird ?

Regard.
0 Kudos

1,449 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Wed Sep 17 00:56:03 MST 2014
Anyway, I can't display i2c_menu, I think I will give up, I don't understand why my clock doesn't work, either with my program, or the nxp_lpcxpresso_11c24_periph_i2c sample, or the other sample i2c in the folder nxp when you install the soft lpcxpresso.
0 Kudos

1,449 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Wed Sep 17 00:34:59 MST 2014
Supply current 1mA max for Vcc = 2,5V.
0 Kudos

1,449 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Wed Sep 17 00:23:16 MST 2014

Quote: Walker91
Cause I use the LPCXpresso Board.



Of course LPCXpressoLPC11c24 is using a voltage converter in LPC-Link to generate 3.3V.

I'm not sure what your EEPROM datasheet is telling you about max write current, my 24AA08 requires max 3mA...





0 Kudos

1,449 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Wed Sep 17 00:16:39 MST 2014

Quote: Walker91
I have to write #define (DEBUG_SEMIHOSTING) ?



Your board.h must define DEBUG_ENABLE and  DEBUG_SEMIHOSTING as shown below...

/** Define DEBUG_ENABLE to enable IO via the DEBUGSTR, DEBUGOUT, and
    DEBUGIN macros. If not defined, DEBUG* functions will be optimized
out of the code at build time.
 */
#define DEBUG_ENABLE

/** Define DEBUG_SEMIHOSTING along with DEBUG_ENABLE to enable IO support
    via semihosting. You may need to use a C library that supports
semihosting with this option.
 */
#define DEBUG_SEMIHOSTING

/** Board UART used for debug output and input using the DEBUG* macros. This
    is also the port used for Board_UARTPutChar, Board_UARTGetChar, and
Board_UARTPutSTR functions.
 */
#define DEBUG_UART LPC_USART

0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Wed Sep 17 00:16:09 MST 2014
Cause I use the LPCXpresso Board.
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Wed Sep 17 00:13:35 MST 2014

Quote: Walker91
An other question, I supply my LPC11C24 only with USB, maybe I have to provide 3V3 on the fit pin for the SCL clock ?



Sorry, I don't understand how a LPC11C24 can be supplied by 5V USB...
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Wed Sep 17 00:12:39 MST 2014
I have to write #define (DEBUG_SEMIHOSTING) ?
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Tue Sep 16 23:59:50 MST 2014

Quote: Walker91
Ok fine. I try to display the i2c_menu from this working sample, I change the C library to Redlib (semihost) in project -> properties, but nothing display on my console. How can do that ?



Is semihosting enabled in your board library?

http://www.lpcware.com/content/faq/lpcopen-debug-inputoutput-support
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Tue Sep 16 23:42:13 MST 2014
Ok fine. I try to display the i2c_menu from this working sample, I change the C library to Redlib (semihost) in project -> properties, but nothing display on my console. How can do that ?
An other question, I supply my LPC11C24 only with USB, maybe I have to provide 3V3 on the fit pin for the SCL clock ?

Regard.
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Tue Sep 16 22:35:11 MST 2014

Quote: Walker91
...normally data are stored automatically in the EEPROM ?



Of course.

At this point I would strongly recommend to step back and restart this project  :O

There's a working (at least to address an I2C device) sample, which has enough potential and could help you to check you hardware  :)

After verifying your hardware with this sample EEPROM access should be possible with changing transmit / receive buffers...


0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Tue Sep 16 10:00:11 MST 2014
Maybe but it makes two weeks that I'm trying to communicate with this EEPROM... Though I did exactly the same things that it's describe in the user manual LPC11C24 to use the I2C bus. It's the good address, I send a byte 0x00 before sens data like indicate in the datasheet of the EEPROM...I don't understand. I don't use buffer like the sample in my program, if I send the EEPROM address, normally data are stored automatically in the EEPROM ?

Regard.
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Tue Sep 16 07:40:52 MST 2014

Quote: Walker91
Maybe it doesn't work cause I don't use the CMSIS Library ?



No. We are not talking about DSP libraries. LPCOpen is including CMSIS:

http://www.lpcware.com/content/faq/lpcxpresso/cmsis-support

If you use a LPCOpen sample or create a new LPCOpen project, nothing else is required.

Anyway, LPCOpen I2C sample should at least detect your I2C EEPROM and verify a correct hardware  :)

Reading and writing EEPROM in this sample will probably fail because this sample is no EEPROM sample and so it's not writing a (memory) address. Since this sample is using a read/write buffer it's easy to change and shouldn't be too difficult to get your EEPROM running...

It's working at least with a Microchip SOT23-5 24AA08...
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Tue Sep 16 07:14:17 MST 2014
I don't find how to use the Semi-hosting option. It's very strange, SDA and SCL are always in high state. I can have a start condition and transmit in the DATA_BUFFER the address of the EEPROM but I never receive ACK or NACK, probably cause the clock doesn't work. And is it normal that CONSET and CONCLR are the same value ?
Please, someone must help me^^.

Regard.
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Mon Sep 15 23:49:39 MST 2014
Ok, it's still a little fuzzy for me. I don't use CMSIS. When I create a new project I choose "LPCOpen - C Project", and put folder in "LPCOpen Chip Library Project" and "LPCOpen Board Library Project" provide with "lpcopen_v2_00a_lpcxpresso_nxp_lpcxpresso_11c24" and choose "None" for "CMISI DSP Library". Maybe it doesn't work cause I don't use the CMSIS Library ?

Regard.
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Mon Sep 15 10:30:38 MST 2014

Quote: Walker91
What does it mean IIRC ?



http://en.wiktionary.org/wiki/IIRC


Quote: Walker91
There is an example of use I2C in the library "lpcopen_v2_00a_lpcxpresso_nxp_lpcxpresso_11c24", but it uses UART and slave mode, whereas I just want to use master mode. My colleague says that I don't configure the lpc11c24 like a master, what do you think about that ?



:quest:

LPCOpen sample nxp_lpcxpresso_11c24_periph_i2c is using DEBUGOUT/DEBUGIN which can be UART or Semihosting...

In detail that means that a LPCOpen project (Semihosting) with working Board Library (Semihosting enabled) can be used to detect attached I2C devices  :)  :)

See:  '3: Probe for Slave devices'

And you should also be able to scope SDA & SCL signals with that option...

I'm not sure what your code is doing. It looks like a mixture of LPCOpen and older CMSIS sample code...
Since it's no complete project it's not possible to test it...
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Mon Sep 15 06:30:56 MST 2014
What does it mean IIRC ? There is an example of use I2C in the library "lpcopen_v2_00a_lpcxpresso_nxp_lpcxpresso_11c24", but it uses UART and slave mode, whereas I just want to use master mode. My colleague says that I don't configure the lpc11c24 like a master, what do you think about that ?

Regard.
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Mon Sep 15 03:13:48 MST 2014
IIRC there's a LPCOpen11C24 I2C sample which can detect  I2C slaves  :)

Did you try that already?
0 Kudos

1,456 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Walker91 on Mon Sep 15 01:36:22 MST 2014
It's 7-bit address + bit R/W. Normally it's the correct address, I saw a sample program which use the same address. An other problem, when I debug my project, the state LPC_I2C -> STAT never change, that why I put in comment the "Wait for complete" in I2C_Start function, otherwise the program never leaves the loop. May be the speed is too high for slave ?
0 Kudos