Write/Read 24AA00 E2PROM with LPC1114

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Write/Read 24AA00 E2PROM with LPC1114

1,925 次查看
thiagorodrigues
Contributor II

Hello,

I´ve been trying to read/write a small EEPROM memory via I2C functions as attached, but it does not seem to work.

In my code I call:

static uint8_t bufeprom[2];

static uint8_t bufeprom1[2];

static uint8_t bufread1[1];

static uint8_t bufread2[1];

I2C_Init(I2CMASTER, 0, 0, 0);

I2C_Read(0xA0, bufread1, 1);

//read EEPROM

I2C_Read(0xA0, bufread2, 1);

/////////////////////

bufeprom[0] = 0x01;

bufeprom[1] = 0x10;

bufeprom1[0] = 0x02;

bufeprom1[1] = 0x10;

I2C_Write(0xA0, bufeprom, 2);

I2C_Write(0xA0, bufeprom1, 2);

After the I2C_Init, I send two read commands to read 1 byte each, since the memory address is incremented automatically by the 24AA.

The write procedure has two parameters, the address and the data to be written, so two comands are sent for two bytes (addresses 0x01 and 0x02).

I´ve tried a lot of things and nothing. And yes, the 24AA has pull-up resistors on the SDA and SCL lines.

Does anyone has experience with LPC and E2PROM memories?

Regards,

0 项奖励
回复
8 回复数

1,647 次查看
jeremyzhou
NXP Employee
NXP Employee

Hi Thiago rodrigues,

Thank you for your interest in NXP Semiconductor products and
for the opportunity to serve you.
Firstly, I'd like to suggest you use the Logic analyzer or to visualize the signal of the I2C transmit, it will help you figure the issue efficiently,
Secondly, I've attached an I2C demo project, please refer to it for details.

Have a great day,
TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 项奖励
回复

1,647 次查看
ianbenton
Senior Contributor I

think this is the problem:

We tend to think of the control byte as being 0xA0 (or 0xA1 for a read) because the lsb indicates read or write, but the LPC I2C module thinks of it as a 7-bit address, ignoring the lsb, so should you actually be specifying the address as 0x50?

It caught me out when I first tried it (but as Jeremy suggested, I found the problem with the oscilloscope)

0 项奖励
回复

1,647 次查看
thiagorodrigues
Contributor II

Well, some updates:

I used an AVR (have more experience with that family) to read/write the E2PROM on the LPC board. It is working. I was able to read/write. It works with both addresses (0x50 and 0xA0). 

So, there must be a problem with the LPC I2C code... because I tried to write to the memory with LPC and read with the AVR, and nothing was written.

Have to keep working :smileyhappy:

0 项奖励
回复

1,647 次查看
ianbenton
Senior Contributor I

I knew I'd had the I2C working on an LPC11, but it's taken be until now to remember why I wrote it.

It must have caused me some trouble at the time, because it looks like I broke it up into very small pieces to test.

It runs a DS1338 real-time clock, but it's the same as reading the small (<256 byte) eeproms. Here's the code I used. It doesn't look like the best possible code, because it doesn't check that the I2C has gone into the correct state, but it obviously worked.

It beggars belief that using the I2C has to be so complicated. It takes more software overhead than the CANBUS.

I mean, NXP invented I2C (back when they were Philips) so why do all their competitors have an easier-to-use interface?

The LPC8 and LPC15 have a slightly different but just as complicated interface and the software is not interchangeable with the LPC11 and LPC13.

            @ Set up I2C

            LDR R3,=LPC_I2C_BASE

            MOVS R2,#150

            STR R2,[R3,SCLH]      // clock high time

            STR R2,[R3,SCLL]  // clock low time

@-------------------------------------------------------------------------------------

                @ set up real time clock

BL read_rtc

// This section writes 0b00010000 to address 7 of the RTC which has a slave address of 0xD0 

// (or 0x68 followed by the R/W bit).

MOVS R0,#0b11010000

BL i2csta

  MOVS R0,#0x7

  BL i2cwrite

  MOVS R0,#0b00010000   @ enable 1Hz output

  BL i2cwrite

  BL i2cstp

@-------------------------------------------------------------------------------------

// this section write zero to the address register of the RTC

LDR R4,=rtc_data           @ address to save time and date in RAM

MOVS R0,#0b11010000

BL i2csta

  MOVS R0,#0x0

  BL i2cwrite

// then reads 9 byte from the RTC and store them in memory.

MOVS R0,#0b11010001   @ read bytes from RTC

BL i2crsta   @ and store in RAM

BL i2cread

STRB R0,[R4]

BL i2cread

STRB R0,[R4,minutes]

BL i2cread

STRB R0,[R4,hours]

BL i2cread

STRB R0,[R4,#3]

BL i2cread

STRB R0,[R4,date]

BL i2cread

STRB R0,[R4,month]

BL i2cread

STRB R0,[R4,year]

  BL i2cread

STRB R0,[R4,#7]

  BL i2crna

STRB R0,[R4,rf_channel]

  BL i2cstp

  POP {R4,PC}

@-------------------------------------------------------------------------------------

@-------------------------------------------------------------------------------------

@ I2C routines

@-------------------------------------------------------------------------------------

i2csta:         LDR R3,=LPC_I2C_BASE   @ START

MOVS R2,#0b01100000

STR R2,[R3,CONSET]

MOVS R1,#0b1000

waitsta: LDR R2,[R3,CONSET]                         @ wait for interrupt flag

TST R2,R1

BEQ waitsta

STR R0,[R3,DAT]

MOVS R2,#0b101000                          @ and clear it and clear STA

STR R2,[R3,CONCLR]

waitsta2: LDR R2,[R3,CONSET]                         @ wait for interrupt flag

TST R2,R1

BEQ waitsta2

BX LR

@-------------------------------------------------------------------------------------

i2crsta:        LDR R3,=LPC_I2C_BASE   @ RESTART

MOVS R2,#0b01100000

STR R2,[R3,CONSET]

MOVS R2,#0b1000

STR R2,[R3,CONCLR]

MOVS R1,#0b1000

waitrsta: LDR R2,[R3,CONSET]                         @ wait for interrupt flag

TST R2,R1

BEQ waitrsta

STR R0,[R3,DAT]

MOVS R2,#0b101000                          @ and clear it and clear STA

STR R2,[R3,CONCLR]

waitrsta2: LDR R2,[R3,CONSET]                         @ wait for interrupt flag

TST R2,R1

BEQ waitrsta2

BX LR

.ltorg

@-------------------------------------------------------------------------------------

i2cstp:         LDR R3,=LPC_I2C_BASE   @ STOP

MOVS R2,#0b01010000

STR R2,[R3,CONSET]

                MOVS R2,#0b1000

STR R2,[R3,CONCLR]

BX LR

@-------------------------------------------------------------------------------------

i2cwrite:       LDR R3,=LPC_I2C_BASE   @ WRITE

STR R0,[R3,DAT]

MOVS R2,#0b1000

STR R2,[R3,CONCLR]

    MOVS R1,#0b1000

waitwr:         LDR R2,[R3,CONSET]

TST R2,R1

BEQ waitwr

                BX LR

@-------------------------------------------------------------------------------------

i2cread:        LDR R3,=LPC_I2C_BASE   @ READ

MOVS R2,#0b100

STR R2,[R3,CONSET]

    MOVS R2,#0b1000

STR R2,[R3,CONCLR]

waitrd:         LDR R2,[R3,CONSET]

TST R2,R1

BEQ waitrd

LDR R0,[R3,DAT]

BX LR

@-------------------------------------------------------------------------------------

i2crna:         LDR R3,=LPC_I2C_BASE                        @ read with no acknowledge

    MOVS R2,#0b100

STR R2,[R3,CONCLR]

    MOVS R2,#0b1000

STR R2,[R3,CONCLR]

waitrn:         LDR R2,[R3,CONSET]

TST R2,R1

BEQ waitrn

LDR R0,[R3,DAT]

BX LR

0 项奖励
回复

1,647 次查看
thiagorodrigues
Contributor II

That is some nice code :smileyhappy: I´ll check it out.

I agree with you about the I2C issues... many years ago I was working a lot with I2C to program digital TV tuners, back in the day it wasn´t so weird... the problem, I think, is the tools available for the different MCUs. Some families (even from different manufacturers) have much better compilers with lots of ready to use libraries, and some others are not that great... like I mentioned, when I used the AVR, in less than 2 minutes I had the code working on the first try. I´m currently using the IAR Embedded for the LPC, but I´m gonna give the KEIL a try... but not very excited about it.

0 项奖励
回复

1,647 次查看
ianbenton
Senior Contributor I

Thanks. Perhaps I should add a check that the slave has actually responded! (But what should it do if there is no ACK?) I have already assumed single master (so no ability to cope with data collisions). 

I have never thought much of the available drivers, and generally end up writing a much more concise version in assembler. GPIO drivers are the worst - taking dozens of lines of code to do what assembler can do in two instructions.

With NXP it is the documentation that goes with the drivers that really lets them down. Example code is of little use without an explanation of what it does and why.

0 项奖励
回复

1,647 次查看
thiagorodrigues
Contributor II

Hello Ian,

That´s interesting, because this was the first address I used when started modifying the code to work with the E2PROM. Since it didn´t work, I switched to 0xA0, but it totally makes sense (I agree with you, by LSB is not part of the address by the I2C standard). After that, I made a lot of other modifications on the code, so maybe the 0x50 address wasn´t the problem after all. I´m gonna give it another try. Although I´ve seen some code to read/write to the same E2PROM using other microcontrollers where the address 0xA0 is being used... strange.

Another thing that I don´t see in the original code is the NACK after reading the byte. This is mandatory for reading functions...

0 项奖励
回复

1,647 次查看
thiagorodrigues
Contributor II

Hello jeremyzhou

Thanks for the file. I´ll take a look into it, and see if I can integrate it into my code.

Although I think it would be better (maybe easier) to use a LPC with internal EEPROM, like LPC11A14... :smileyhappy:, right?

Regards,

0 项奖励
回复