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