lpc2119 I2C Problem with SRF02

Started by faiz...@hotmail.com July 28, 2009
Hi all

im trying to communicate with my sensor which is the SRF02.
Ive got a LPC2119 with the eval board.

Can someone help me ??

#define STA 0x20 //100000
#define SIC 0x08 //1000
#define SI 0x08 //1000
#define STO 0x10 //10000
#define STAC 0x20 //100000
#define AA 0x04 //100

unsigned char DataL; // Low data byte storage
unsigned char DataH; // High data byte storage
unsigned int data; // Data storage (DataH:DataL)

void InitI2C(void) {
I2CONCLR = 0x36;
I2SCLL = 393;
I2SCLH = 393;
I2CONSET = 0x40;
}

void SendAddressI2C(unsigned char Addr) {

I2CONCLR = 0x36;
I2CONSET = 0x40;
if(Addr & 0x01)
{
I2CONSET = STA | AA;
}
else
I2CONSET = STA;
while(I2STAT!=0x08) ;

I2CONCLR = SIC | STAC;
while( ! ( I2CONSET & SI)) ;
}

unsigned char ReadI2C(void) {
I2CONCLR = SIC;
while( ! (I2CONSET & 0x8));
return I2DAT;
}

void StopI2C(void) {

I2CONCLR = SIC;
I2CONSET = STO;
while((I2CONSET&STO));
}

int main(void)
{
InitI2C();
SendAddressI2C(0xE0);
SendAddressI2C(0x00);
SendAddressI2C(0x51);
StopI2C();
delay();//wait 65mS

InitI2C();
SendAddressI2C(0xE0);
SendAddressI2C(0x02);
DataL=ReadI2C();
I2CONSET = STA;//repeated start
SendAddressI2C(0xE1);
DataH=ReadI2C();
StopI2C();

*((unsigned char *)(&data))aL;
*((unsigned char *)(&data)+1)aH ; //dataaH:DataL
return 0;
}

after sending adress SendAddressI2C(0xE0)ive got I2STAT 0x08
SendAddressI2C(0x00)=>I2STAT 0x18
SendAddressI2C(0x51)=> I2STAT 0x28
Thank You

An Engineer's Guide to the LPC2100 Series

--- In l..., faizal93200@... wrote:
>
> Hi all
>
> im trying to communicate with my sensor which is the SRF02.
> Ive got a LPC2119 with the eval board.
>
> Can someone help me ??

I think there are better examples of I2C code in the Files folder. In general, I2C is best implemented as an interrupt driven state machine although the sample files do not take that approach. Maybe you can adapt something from the samples.

There is a very nice implementation at www.jcwren.com/arm

Richard
--- 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.
Here my new code
void send adress()
{
unsigned char Addr1,Addr2;
Addr1=0xE0;
Addr2=0x00;
int transfert =0;
I2CONCLR = 0x36;
I2CONSET = 0x40;

while(transfert!=1)
{

if(Addr1 & 0x01)// test if it's reading
{ I2CONSET = STA | AA;

}
else

I2CONSET = 1UL<<5; //START

switch(I2STAT)
{

case 0x08:
I2DAT = Addr1;
I2CONCLR =(1UL<<3|1UL<<5);
while( ! ( I2CONSET & (1UL<<3))) ; // Wait till status available
break;

case 0x18:
I2DAT = Addr2;
I2CONCLR =(1UL<<3|1UL<<5);
while( ! ( I2CONSET & (1UL<<3))) ;
break;

case 0x28:
I2CONCLR = SIC;
I2CONSET = STO;
transfert=1;

break;

}

}
}

--- 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

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
>
>
>