One of the problems I faced with my I2C implementation was that it would
always stuck in one of the states. I had state machine exactly it was
supposed to be in the documentation I was following but still it would not
work. Then, I tried clearing something that wasn't necessary according
to
the documentation, then only it worked. I can't remember exactly what I
had
to do, but I do remember that I had to clear a bit that wasn't
mentioned.
Here's my state machine that works on LPC2106.
void ItwoCinterface_ISR(void)
{
// Increment the system tick, clear and reset the interrupt
static Uint32 toggle = 0;
//if(toggle) GPIO_IOCLR = IO_TEST_PIN;
//else GPIO_IOSET = IO_TEST_PIN;
//toggle = !toggle;
volatile Uint32 temp = I2C_I2STAT;
switch(temp & 0xFF)
{
case START_CONDITION_TRANSMITTED:
I2C_I2DAT = SLAVE_ADDRESS | i2c_interface.read_or_write;
I2C_I2CONSET = I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('o');
break;
case REPEAT_START_CONDITION_TRANSMITTED:
I2C_I2DAT = SLAVE_ADDRESS | i2c_interface.read_or_write;
I2C_I2CONSET = I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('0');
break;
case ACK_RECEIVED_FOR_START_CONDITION:
I2C_I2DAT = i2c_interface.command_to_send & 0xFF;
I2C_I2CONSET = I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_STAC | I2CONCLR_SIC;
// uart0Putch('1');
break;
case NO_ACK_RECEIVED_FOR_START_CONDITION:
I2C_I2CONSET = I2CONSET_STO | I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('2');
break;
case ACK_RECEIVED_FOR_DATA_TRANSMISSION:
I2C_I2CONSET = I2CONSET_STO | I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('3');
break;
case NO_ACK_RECEIVED_FOR_DATA_TRANSMISSION:
I2C_I2CONSET = I2CONSET_STO | I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('4');
break;
case LOST_ARBITRATION:
I2C_I2CONSET = I2CONSET_STA | I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('5');
break;
case ACK_RECEIVED_FOR_DATA_RECEIVE_READY:
I2C_I2CONSET = I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_STAC;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('6');
break;
case NO_ACK_RECEIVED_FOR_DATA_RECEIVE_READY:
I2C_I2CONSET = I2CONSET_STO | I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('7');
break;
case ACK_RECEIVED_FOR_DATA_RECEIVE:
i2c_interface.data_received
&~(0xFF<
i2c_interface.data_received |= (I2C_I2DAT & 0xFF) <<
(i2c_interface.data_received_count*8);
if(i2c_interface.data_received_count != 3)
{
I2C_I2CONSET = I2CONSET_AA;
I2C_I2CONCLR = I2CONCLR_SIC;
i2c_interface.data_received_count++;
// uart0Putch('8');
}
else
{
i2c_interface.data_ready = TRUE;
i2c_interface.data_received_count = 0;
I2C_I2CONCLR = I2CONCLR_SIC | I2CONCLR_AAC;
// uart0Putch('9');
}
break;
case NO_ACK_RECEIVED_FOR_DATA_RECEIVE:
I2C_I2CONSET = I2CONSET_STO;
I2C_I2CONCLR = I2CONCLR_SIC;
// uart0Putch('A');
break;
default:
// uart0Putch('B');
break;
}
VICVectAddr = 0;
return;
}
Goodluck.
-Ananda
On Wed, Jul 29, 2009 at 7:06 PM, rtstofer wrote:
> --- In l... ,
"faisal_b2o"
> wrote:
> >
> > --- In l... , "rtstofer"
> wrote:
> >
> > I tried to check the code for I2C in that website, it seems different
> from mine.
> >
> > I have made some change and now I can send an adress. Thats means for the
> SRF02 example
> > I can send 0xE0 which is the sensor adress
> > send 0x00 internal command register
> > and 0x51 which is to start a ranging in centimeter.
> >
> > Now I would like to read this value.
> >
> > According to some website.
> >
> > We have to
> > Send 0xE0
> > Send 0x02
> > read Data low
> > Send 0xE1
> > read data high
> >
> > But Im not able to do this.
>
> That's because at least half the required code is missing. I2C is the
> second most difficult protocol to get working right after USB. Personally,
I
> don't think it can be done without a logic analyzer but that's
because I
> have a short attention span and an analyzer.
>
> Part of the problem is that there is no standard way to talk to I2C devices
> in terms of addressing internal data and subsequently reading the data.
Some
> devices want a single byte command, some want a 2 byte address followed by
a
> single byte command, some want it the other way around.
>
> Maybe the code in this file will help LPC214x_LPC213x Sample Code for
> ARM-RVDK.zip in the FILES folder. This code is provided by NXP.
>
> A long while back, I wrote an MP3 player for the LPC2106 and it used an I2C
> based LCD display. I have posted the code in the FILES folder as
> ARMRevisedMP3Player.zip I'll delete it in a couple of days.
>
> The I2C stuff is interrupt driven and you should probably start by looking
> at how the LCD code uses the I2C code. I2CMasterReceive isn't used in
this
> project but I believe it works.
>
> Note that the code is interrupt driven so there are setup requirements for
> the VIC, see setup.c Further, interrupts need to be enabled in crt.s
>
> You might just try to take my state machine and run it without interrupts.
> I don't know if it will work.
>
> Frankly, I like jcwren's code better. But mine worked at one time.
>
> Richard
>
>
>