I2C on LPC1343

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

I2C on LPC1343

11,302 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by JohnBurton on Thu Jul 15 10:07:06 MST 2010
I'm trying to use the I2C on an LPC1343 LPCXpresso board to read and write an EEPROM chip.

I've taken the example code from the I2C sample and adapted it.
I've set the A0,1,2 pins on the chip to 0,and connected the SDA and SDC lines to the board with pullup resistors too.

The code I'm trying to use looks like this - but it never reads anything back. Most worryingly if I remove the chip entirely just keeping the pins with the pullups then it does exactly the same.

Is there anything else I have to do to make this work? I'm presuming I2CInit will set up the hardware settings required for this? Or am I missign something else I need to do?

Thanks for any suggestions


#define EEPROM_ADDR 0xA0

int main(void)
{
int f;
I2CInit(I2CMASTER);

// Write the byte 0xFD into location zero in the EEPROM
I2CWriteLength = 4;
I2CReadLength  = 0;
I2CMasterBuffer[0] = EEPROM_ADDR;
I2CMasterBuffer[1] = 0x00;// 2 byte address zero
I2CMasterBuffer[2] = 0x00;
I2CMasterBuffer[3] = 0xFD;
I2CEngine();

// And read it back, should appear at IC2MasterBuffer[3 + 2] ...?
I2CWriteLength = 3;
I2CReadLength  = 1;
I2CMasterBuffer[0] = EEPROM_ADDR;
I2CMasterBuffer[1] = 0x00;// 2 byte address zero
I2CMasterBuffer[2] = 0x00;
I2CMasterBuffer[3] = EEPROM_ADDR | RD_BIT;
I2CEngine();

return 0 ;
}
0 Kudos
Reply
74 Replies

2,697 Views
Tonmaker
Contributor I

Hello everyone,

I'm migrating my project to ARM, LPC1343 and I'm having difficulties with I2C, I did the initialization but when it gets to the line LPC_I2C->CONSET = (1 << 5); // STA the MCU stops, I put a serial debug to check as follows
sprintf(string, "CONSET STA INIT - VALUE: %04X\r\nSTAT REG: %04X\r\n", LPC_I2C->CONSET, LPC_I2C->STAT);
uart_enviar(string);
LPC_I2C->CONSET = (1 << 5); // STA
sprintf(string, "CONSET STA OK - VALUE: %04X\r\nSTAT REG: %04X\r\n", LPC_I2C->CONSET, LPC_I2C->STAT);
uart_send(string);
the second uart is not executed

see the monitor

CONSET 0040
STAT 00F8
I2C START
CONSET STA INIT - VALUE: 0040
STAT REG: 00F8

should appear next CONSET STA OK

this is the I2C initialization
uint32_t I2CInit( uint32_t I2cMode ) {
test(16);
LPC_SYSCON->PRESETCTRL |= (0x1<<1);
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
LPC_IOCON->PIO0_4 &= ~0x3F; /* I2C I/O config */
LPC_IOCON->PIO0_4 |= 0x01; /* I2C SCL */
LPC_IOCON->PIO0_5 &= ~0x3F;
LPC_IOCON->PIO0_5 |= 0x01; /* I2C SDA */
/*--- Clear flags ---*/
test(17);
LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;

/*--- Reset registers ---*/
test(18);
#if FAST_MODE_PLUS
test(19);
LPC_IOCON->PIO0_4 |= (0x2<<8);
LPC_IOCON->PIO0_5 |= (0x2<<8);
LPC_I2C->SCLL = I2SCLL_HS_SCLL;
LPC_I2C->SCLH = I2SCLH_HS_SCLH;
test(20);
#else
test(21);
LPC_I2C->SCLL = I2SCLL_SCLL;
LPC_I2C->SCLH = I2SCLH_SCLH;
test(22);
#endif

The clock is at 72Mhz

What is missing?

0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by BPC on Wed Jan 23 10:42:07 MST 2013
I suggest looking at the i2c example provided by NXP.
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by niki on Wed Jan 23 10:34:15 MST 2013
void I2C_Init()
{
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
    LPC_SYSCON->PRESETCTRL = I2C_RST_N;    //de-reset
    LPC_IOCON->PIO0_4 = (0x001);           //podesavanje P.4 za I2C
    LPC_IOCON->PIO0_5 = (0x001);           //podesavanje P.5 za I2C
    LPC_I2C->SCLH = (120);
    LPC_I2C->SCLL = (120);
    LPC_I2C->CONCLR = (0x6C);
    LPC_I2C->CONSET |= (I2EN);

    NVIC_EnableIRQ(I2C_IRQn);

}
my init function look lik this
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by BPC on Wed Jan 23 09:35:02 MST 2013
What does your Init function look like?
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by niki on Wed Jan 23 09:09:05 MST 2013
Ok  i'm beginer with ARM.How i shoud enable I2C interrupt(with this function NVIC_EnableIRQ(I2C_IRQn) which i'm includ in my Init function) or  i need something else.

I'm using TMP75 with 1.8k pull-up on both lines.I'm using LPC Xpresso for programming.

Thanks for help
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Tue Jan 22 15:10:39 MST 2013

Quote: niki
also i notic when Si is set in CONSET that is set also in CONCLR.Can enybody help?



You should read the user manual. Conclr is a write only register!

When your interrupt routine is not called, check the code that enables the interrupts.
Which code do you use, which program, what kind of a device is connected to the I2C bus, do you have pull-up resistors on both the SCl and SDA lines.
Just stating that your interrupt is not called is too few information to make even an educated guess...

Rob
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by niki on Tue Jan 22 03:57:24 MST 2013
I have a trouble with I2C_IRQHandler becouse my program doesn't go  in I2C_IRQHandler when SI flag is set,also i notic when Si is set in CONSET that is set also in CONCLR.Can enybody help?
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Tue Nov 06 07:37:34 MST 2012

Quote: groufosse
The code gets to the line where " I2CEngine();" is called, after all the I2CMasterBuffer variables are set. It never comes back from that call.


Are you sure the interrupt is working?
The I2CEngine() just triggers the I2C peripheral to start a transaction. From there on, the I2C peripheral is generating interrupts.

I2CEngine() waits for the I2CMasterState to reach a terminating state in the state engine in the I2C_IRQHandler. If the interrupt routine is not being called then the transaction will never complete.


Quote:

Any suggestion as to what I might look for to figure this out? Due to the nature of the call, the debugger can't step through it either.


Strange ... On the LPCXpresso IDE I am able to step through all the code, including the full state machine in the interrupt handler.

It looks like your interrupt is messing up your system such that debugging stops working.

Rob
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by groufosse on Mon Nov 05 15:26:45 MST 2012

Quote: Rob65
Done!
The attachment contains the updated driver as an exported Code Red project.
Note that I did this on an LPC1114 module, you need to change the references to the LPC11xx.h header file for an lpc13xx.

I changed the state machine in the interrupt:

[LIST]
[*]Added some comment to clarify the different states
[*]removed the assignments to I2CMasterState (these were not used).
[*]Changed I2CMasterState to give the result of the transaction
[*]fixed a bug (on a read there was actually one byte more read than requested).
[*]Added consequent handling for sending a STOP condition removing the need to send a STOP condition from I2CEngine()
[/LIST]
I also added a timeout to I2CStop() and the I2CEngine now returns a transaction result.

The i2ctest.c is almost the same, all I did was a small change to use a 24LC08 EEPROM as a device and I added a check on the EEPROM read.
The 24LC08 will return a NACK on the slave address as long as it is writing the data to EEPROM. When this happens the I2CEngine will return the I2CSTATE_SLA_NACK value and the test program will loop until an actual read has taken place.

There is also a screendump from the logic analyzer available showing all transactions but that image is too large for this forum. The image is available at: http://myvoice.nl/software/#XpressoDrivers

If there still is anything wrong with this driver feel free to shoot me (ehh... drop me an email) and I'll try to fix it.

Some notes:

[LIST]
[*]no real documentation added
[*]no extensive testing on fault conditions, the states 0x30, 0x38 and 0x48 in the state machine have not been tested
[*]I did not check all existing comments, there may still be some faulty comments
[*]the I2C clock is set to 400 kHz on the lpc1114, besides editing the i2c.h file there is no means to change the clock frequency.
[/LIST]
Regards,

Rob



Hi Rob,

I'm new to using I2C, and taking a stab at using your sample. I've got it added into my IAR project. The code gets to the line where " I2CEngine();" is called, after all the I2CMasterBuffer variables are set. It never comes back from that call.

Any suggestion as to what I might look for to figure this out? Due to the nature of the call, the debugger can't step through it either.

In my case, I've changed the references to include "LPC17xx.h"

Thanks,
Gary
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Thu Mar 08 10:47:37 MST 2012
Hm,

apparently my own website does not contain the latest version of my own driver :eek: this is kind of embarrassing ...

Finding my own driver is not a problem now that I'm back at my development PC. It was just not committed to my Mercurial archive yet.
I've been wanting to add the driver to my standard "Platform1754"  project but I try to only submit driver there when they are thoroughly tested.
To make it up to you I decided to submit the I2C driver. It is working (I am sure of this) and I have used it with the MMA8453 and a 24LC08 EEPROM but it has not been fully qualified in my stress-test FreeRTOS environment.

Please note that this is a FreeRTOS version of my I2C driver. As far as I know all dependencies are enclosed using a #define FREERTOS (which you may want to undefine when you are not using FreeRTOS).
Also, the driver is currently being used with an LPC17xx so you should look at the I2CInit() inside the old version for the lpc1343.

The driver can be found in the lpc17xx and the include file in the include directory in my archive here.

Regards,
[INDENT]Rob
[/INDENT]
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tinrik on Thu Mar 08 09:52:33 MST 2012
But still I can't find an I2CEngine(i2cWriteBuffer, &i2cWriteLength, i2cReadBuffer, &i2cReadLength) in that file, there's just an I2CEngine([B]void[/B])...
So I can't use your implementation below =( I hope you can find your own driver, I haven't found anything else on the Internet...

Regards
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Thu Mar 08 08:38:54 MST 2012
Sorry, I had a bit of problem locating it at my own website (actually, the website itself has been taken down - only some special pages are still available).

You can find the i2c_driver_v1.10.zip file here.

Regards,[INDENT]Rob
[/INDENT]
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tinrik on Thu Mar 08 05:00:08 MST 2012
Anyone knows where to find the updated I2C libraries for the LPC1343?

Thanks in advance.
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tinrik on Tue Mar 06 14:59:48 MST 2012
That's exactly what I was looking for, thank you very much!!

There's a detail, though: It seems I have an old library for I2C. I downloaded the "examples.lpc13xx.zip" file from the NXP site: http://ics.nxp.com/support/lpcxpresso/zip/examples.lpc13xx.zip

And got the libraries from the i2c folder.

However, you use an I2CEngine function which receives some parameters, whereas mine is defined as I2CEngine(void). Could you tell me where can I find the updated libraries you have, please? (or, if possible, could you post them? (i2c.c and i2c.h ) )

Thank you again, you've been really helpful!
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Tue Mar 06 10:26:52 MST 2012

Quote: Tinrik
MMA8543Q accelerometer.



Just checked - I have the MMA8453Q
Luckily your copy/pasted text from the datasheet shows me you swapped some digits (I keep reminding my colleagues that's a common problem that we geniuses have :D)

Here is the code to write and read a register from the chip:
uint8_t write_register(uint8_t i2cReg, uint8_t i2cData)
{
    i2cWriteLength = 3;
    i2cReadLength  = 0;
    i2cWriteBuffer[0] = i2cSlaveAddr;
    i2cWriteBuffer[1] = i2cReg;
    i2cWriteBuffer[2] = i2cData;

    return (I2CEngine(i2cWriteBuffer, &i2cWriteLength, i2cReadBuffer, &i2cReadLength) == I2CSTATE_ACK);
}

uint8_t read_registers(uint8_t i2cReg, uint8_t *buffer, uint8_t length)
{
    i2cWriteLength = 2;
    i2cReadLength  = length;

    i2cWriteBuffer[0] = i2cSlaveAddr;
    i2cWriteBuffer[1] = i2cReg;
    i2cWriteBuffer[2] = i2cSlaveAddr | RD_BIT;

    return I2CEngine(i2cWriteBuffer, &i2cWriteLength, buffer, &length);
}
And this is what I do to start the sensor to measure:
    write_register(0x2c, 0x00);
    write_register(0x2d, 0x01);
    write_register(0x2e, 0x01);
    write_register(0x2a, 0x11); /* 200 Hz sampling rate */
Good thing I added a comment because I don't remember what those registers do on top of my head ...

And here is the reading of the data registers:

    uint16_t sensorData[3];

        for(i=0; i<3; i++)
        {
            read_registers(0, i2cReadBuffer, 7);
            if(i2cReadBuffer[0]) break;
        }

        if(i2cReadBuffer[0] & 1)
            sensorData[0] = (i2cReadBuffer[1] << 8) | i2cReadBuffer[2];
        else
            sensorXErr++;
        if(i2cReadBuffer[0] & 2)
            sensorData[1] = (i2cReadBuffer[3] << 8) | i2cReadBuffer[4];
        else
            sensorYErr++;
        if(i2cReadBuffer[0] & 4)
            sensorData[2] = (i2cReadBuffer[5] << 8) | i2cReadBuffer[6];
        else
            sensorZErr++;

The for loop is there to check if there is valid data available.
If not, then I do a retry.

The reason is because using the interrupt is optional in my program (reading can also be done on a timer base) and I want to prevent reading invalid data.

Hope this helps.

Regards,
[INDENT]Rob
[/INDENT]
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Tue Mar 06 08:42:23 MST 2012

Quote: Tinrik
MMA8543Q accelerometer.



If I remember well, I have the same chip but I don't have the code with me.
Will check tonight.

Regards,
[INDENT]Rob
[/INDENT]
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tinrik on Tue Mar 06 06:38:39 MST 2012
Hi,

I'd like to use this library to read the acceleration values of a MMA8543Q accelerometer.
The datasheet says:
The Master (or MCU) transmits a start condition (ST) to the MMA8453Q, slave address ($1D), with the R/W bit
set to “0” for a write, and the MMA8453Q sends an acknowledgement. Then the Master (or MCU) transmits the address of the
register to read and the MMA8453Q sends an acknowledgement. The Master (or MCU) transmits a [B]repeated start condition[/B] (SR)
and then addresses the MMA8453Q ($1D) with the R/W bit set to “1” for a read from the previously selected register. The Slave
then acknowledges and transmits the data from the requested register. The Master does not acknowledge (NAK) the transmitted
data, but transmits a stop condition to end the data transfer.


I would do the following:
I2CWriteLength = 2;
I2CReadLength = 0;
I2CMasterBuffer[0] = 0x1D<<1; //device address with LSB = 0 (Write)
I2CMasterBuffer[1] = ACC_OUT_X_MSB;      //register address
...??
        ...??
        I2CEngine();

My problem is that I have to do a Repeated Start Condition, but if I use I2CEngine() it finishes with a Stop Condition, which I don't want. Could you help on how to follow the procedure in the datasheet to read a byte?

Thanks a lot.
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Fri Nov 11 13:28:53 MST 2011
Hi there,
Lithium, would you send me your code? I'm a beginner trying to run the ith3200/bma180 board together with my lpc1769.
I'm really close now but I'd really appreciate your code as a reference.

Thanks
0 Kudos
Reply

7,086 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Lithium on Thu Apr 14 10:38:56 MST 2011
Rob,

I2C is working for now, the only problem i still have. When connecting my acc I2C stops working. Pull it back out and everything works fine again.
Also found someone with the same problem (with an microchip pic as main).
0 Kudos
Reply

7,083 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Thu Apr 14 10:10:11 MST 2011
Lithium,

if you still need some help, skype rob.65 but that's most likely on my Galaxy-S or the iPad. No skype or teamviewer on my PC (yet)

NXP_Europe,
thanks. If you need any more help or input. skype or call - I'm just about 5 minutes away from your office in Nijmegen.

Regards,
Rob
0 Kudos
Reply