EmbeddedRelated.com
Forums

I2C (slave and master on board)

Started by Jon Trem September 26, 2008
No, I2C1 ports are 0.11 and 0.14 which are in PINSEL0 bits 22,23 and
28,29.
I2C1 is well configured because it acknowledges only his address and
general calling (0x7E and 0x01 with the write bit). When I try to
communicate with I2C0 to another address, I have no acknowledge.

--- In l..., "tcirobot" wrote:
>
> --- In l..., "jon.trem" wrote:
> > ...
> > void initialize_I2C(void) {
> >
> > PINSEL0 |= (1<<4)|(1<<6);
> > PINSEL0 |= (1<<22)|(1<<23)|(1<<28)|(1<<29);
>
> I'm not sure what you intended the second write to PINSEL0 above to do,
> but it does not configure the I2C1 pins. I didn't see in your code
> where you configured the I2C1 SCL and SDA pins. I was looking for the
> something like the following (using your coding style)...
>
> PINSEL1 |= (1<<2)|(1<<4);
>
> I still haven't had a chance to walk through the rest of the code
> carefully.
>
> TC
>

An Engineer's Guide to the LPC2100 Series

--- In l..., "jon.trem" wrote:
>
> No, I2C1 ports are 0.11 and 0.14 which are in PINSEL0 bits 22,23 and
> 28,29.
> I2C1 is well configured because it acknowledges only his address and
> general calling (0x7E and 0x01 with the write bit). When I try to
> communicate with I2C0 to another address, I have no acknowledge.
>

Sorry about the confusion. I was looking at the LPC2103 spec which is
NOT the part you are using. OOOPS!

TC
NOTE: these diagrams may look funny inf NOT viewed with FIXED-WIDTH
fonts.

My understanding is that you are trying to write a byte of data using
I2C0 as the master and I2C1 as the slave. If everything worked I would
expect the I2C transaction to look like this...

START ADDR+W [ACK] DATA [ACK] STOP

... where brackets "[ ]" are used to indicate that the slave is
driving SDA (as opposed to the master).

I would expect to see the following I2C0 (master) interrupts and
states.

START ADDR+W [ACK] DATA [ACK] STOP
^ ^ ^
0x08 0x18 0x28

Your code for the I2C0 ISR seems to anticipate this sequence
correctly. One thing I did notice is that in the I2C0 ISR for state
0x18 you do the following...

I2C0DAT = I2C_address; //Send the slave address and the write bit
I2C0CONCLR = I2C_STA; // Clear the start bit

... I have them in my code in reverse order...

I2C0CONCLR = I2C_STA; // Clear the start bit
I2C0DAT = I2C_address; //Send the slave address and the write bit

I don't know that it matters (but you could try it).

I would expect to see the following I2C1 (slave) interrupts and
states.

START ADDR+W [ACK] DATA [ACK] STOP
^ ^ ^
0x60 0x80 0xA0

Your code for the I2C1 ISR seems to anticipate this sequence
correctly. One thing I did notice is that you don't read the received
data in state 0x80 from I2C1DAT. Maybe I2C1 is holding SCL low (I2C
wait state) until you do. I'd suggest adding the read of the received
data.

One other thing... I also read I2C1DAT in state 0x60 as a diagnostic
function to see what address (and write/read bit) I received as a
slave.

TC

I've tried both but it's still not working.

The address is not a problem because the slave answers (and just when
the address is fine). I also tried to read IC1DAT but LED_2 should
light as soon as I2C1STAT is 0x80 which is not the case. So the
instruction data = I2C1DAT; that I added in case(0x80) is never executed.

I'm really lost! But thanks for your help

--- In l..., "tcirobot" wrote:
>
> NOTE: these diagrams may look funny inf NOT viewed with FIXED-WIDTH
> fonts.
>
> My understanding is that you are trying to write a byte of data using
> I2C0 as the master and I2C1 as the slave. If everything worked I would
> expect the I2C transaction to look like this...
>
> START ADDR+W [ACK] DATA [ACK] STOP
>
> ... where brackets "[ ]" are used to indicate that the slave is
> driving SDA (as opposed to the master).
>
> I would expect to see the following I2C0 (master) interrupts and
> states.
>
> START ADDR+W [ACK] DATA [ACK] STOP
> ^ ^ ^
> 0x08 0x18 0x28
>
> Your code for the I2C0 ISR seems to anticipate this sequence
> correctly. One thing I did notice is that in the I2C0 ISR for state
> 0x18 you do the following...
>
> I2C0DAT = I2C_address; //Send the slave address and the write bit
> I2C0CONCLR = I2C_STA; // Clear the start bit
>
> ... I have them in my code in reverse order...
>
> I2C0CONCLR = I2C_STA; // Clear the start bit
> I2C0DAT = I2C_address; //Send the slave address and the write bit
>
> I don't know that it matters (but you could try it).
>
> I would expect to see the following I2C1 (slave) interrupts and
> states.
>
> START ADDR+W [ACK] DATA [ACK] STOP
> ^ ^ ^
> 0x60 0x80 0xA0
>
> Your code for the I2C1 ISR seems to anticipate this sequence
> correctly. One thing I did notice is that you don't read the received
> data in state 0x80 from I2C1DAT. Maybe I2C1 is holding SCL low (I2C
> wait state) until you do. I'd suggest adding the read of the received
> data.
>
> One other thing... I also read I2C1DAT in state 0x60 as a diagnostic
> function to see what address (and write/read bit) I received as a
> slave.
>
> TC
>

If you are really interested in I2C, go get you a I2C debugger. Total
Phase makes one for a couple hundred bucks. It has saved me
tremendous time getting my I2C peripherals working correctly. It
shows you all the packets and makes short work of any problems.

Sutton

--- In l..., "jon.trem" wrote:
>
> I've tried both but it's still not working.
>
> The address is not a problem because the slave answers (and just when
> the address is fine). I also tried to read IC1DAT but LED_2 should
> light as soon as I2C1STAT is 0x80 which is not the case. So the
> instruction data = I2C1DAT; that I added in case(0x80) is never
executed.
>
> I'm really lost! But thanks for your help
>
> --- In l..., "tcirobot" wrote:
> >
> > NOTE: these diagrams may look funny inf NOT viewed with FIXED-WIDTH
> > fonts.
> >
> > My understanding is that you are trying to write a byte of data using
> > I2C0 as the master and I2C1 as the slave. If everything worked I
would
> > expect the I2C transaction to look like this...
> >
> > START ADDR+W [ACK] DATA [ACK] STOP
> >
> > ... where brackets "[ ]" are used to indicate that the slave is
> > driving SDA (as opposed to the master).
> >
> > I would expect to see the following I2C0 (master) interrupts and
> > states.
> >
> > START ADDR+W [ACK] DATA [ACK] STOP
> > ^ ^ ^
> > 0x08 0x18 0x28
> >
> > Your code for the I2C0 ISR seems to anticipate this sequence
> > correctly. One thing I did notice is that in the I2C0 ISR for state
> > 0x18 you do the following...
> >
> > I2C0DAT = I2C_address; //Send the slave address and the write bit
> > I2C0CONCLR = I2C_STA; // Clear the start bit
> >
> > ... I have them in my code in reverse order...
> >
> > I2C0CONCLR = I2C_STA; // Clear the start bit
> > I2C0DAT = I2C_address; //Send the slave address and the write bit
> >
> > I don't know that it matters (but you could try it).
> >
> > I would expect to see the following I2C1 (slave) interrupts and
> > states.
> >
> > START ADDR+W [ACK] DATA [ACK] STOP
> > ^ ^ ^
> > 0x60 0x80 0xA0
> >
> > Your code for the I2C1 ISR seems to anticipate this sequence
> > correctly. One thing I did notice is that you don't read the received
> > data in state 0x80 from I2C1DAT. Maybe I2C1 is holding SCL low (I2C
> > wait state) until you do. I'd suggest adding the read of the received
> > data.
> >
> > One other thing... I also read I2C1DAT in state 0x60 as a diagnostic
> > function to see what address (and write/read bit) I received as a
> > slave.
> >
> > TC
>
Yes, I'm convinced of this, but I'm a student and I don't really have
the money to invest in a I2C debugger.
--- In l..., "Sutton Mehaffey" wrote:
>
> If you are really interested in I2C, go get you a I2C debugger. Total
> Phase makes one for a couple hundred bucks. It has saved me
> tremendous time getting my I2C peripherals working correctly. It
> shows you all the packets and makes short work of any problems.
>
> Sutton
>
> --- In l..., "jon.trem" wrote:
> >
> > I've tried both but it's still not working.
> >
> > The address is not a problem because the slave answers (and just when
> > the address is fine). I also tried to read IC1DAT but LED_2 should
> > light as soon as I2C1STAT is 0x80 which is not the case. So the
> > instruction data = I2C1DAT; that I added in case(0x80) is never
> executed.
> >
> > I'm really lost! But thanks for your help
> >
> > --- In l..., "tcirobot" wrote:
> > >
> > > NOTE: these diagrams may look funny inf NOT viewed with FIXED-WIDTH
> > > fonts.
> > >
> > > My understanding is that you are trying to write a byte of data
using
> > > I2C0 as the master and I2C1 as the slave. If everything worked I
> would
> > > expect the I2C transaction to look like this...
> > >
> > > START ADDR+W [ACK] DATA [ACK] STOP
> > >
> > > ... where brackets "[ ]" are used to indicate that the slave is
> > > driving SDA (as opposed to the master).
> > >
> > > I would expect to see the following I2C0 (master) interrupts and
> > > states.
> > >
> > > START ADDR+W [ACK] DATA [ACK] STOP
> > > ^ ^ ^
> > > 0x08 0x18 0x28
> > >
> > > Your code for the I2C0 ISR seems to anticipate this sequence
> > > correctly. One thing I did notice is that in the I2C0 ISR for state
> > > 0x18 you do the following...
> > >
> > > I2C0DAT = I2C_address; //Send the slave address and the write bit
> > > I2C0CONCLR = I2C_STA; // Clear the start bit
> > >
> > > ... I have them in my code in reverse order...
> > >
> > > I2C0CONCLR = I2C_STA; // Clear the start bit
> > > I2C0DAT = I2C_address; //Send the slave address and the write bit
> > >
> > > I don't know that it matters (but you could try it).
> > >
> > > I would expect to see the following I2C1 (slave) interrupts and
> > > states.
> > >
> > > START ADDR+W [ACK] DATA [ACK] STOP
> > > ^ ^ ^
> > > 0x60 0x80 0xA0
> > >
> > > Your code for the I2C1 ISR seems to anticipate this sequence
> > > correctly. One thing I did notice is that you don't read the
received
> > > data in state 0x80 from I2C1DAT. Maybe I2C1 is holding SCL low (I2C
> > > wait state) until you do. I'd suggest adding the read of the
received
> > > data.
> > >
> > > One other thing... I also read I2C1DAT in state 0x60 as a
diagnostic
> > > function to see what address (and write/read bit) I received as a
> > > slave.
> > >
> > > TC
> > >
>
Understood. Maybe your department has debugging tools. They should.

I've spent many an hour looking at I2C problems, before I finally
broke down and got a debugger. Problem solved within an hour. I
still have issues occasionally and the debugger is an invaluable tool
to solve problems quickly.

Until then, unfortunately it's questioning yourself on whether your
code is correct or not until you find the problem. You'll find it
eventually.

Sutton

--- In l..., "jon.trem" wrote:
>
> Yes, I'm convinced of this, but I'm a student and I don't really have
> the money to invest in a I2C debugger.
> --- In l..., "Sutton Mehaffey" wrote:
> >
> > If you are really interested in I2C, go get you a I2C debugger. Total
> > Phase makes one for a couple hundred bucks. It has saved me
> > tremendous time getting my I2C peripherals working correctly. It
> > shows you all the packets and makes short work of any problems.
> >
> > Sutton
> >
> >
> >
> > --- In l..., "jon.trem" wrote:
> > >
> > > I've tried both but it's still not working.
> > >
> > > The address is not a problem because the slave answers (and just
when
> > > the address is fine). I also tried to read IC1DAT but LED_2 should
> > > light as soon as I2C1STAT is 0x80 which is not the case. So the
> > > instruction data = I2C1DAT; that I added in case(0x80) is never
> > executed.
> > >
> > > I'm really lost! But thanks for your help
> > >
> > > --- In l..., "tcirobot" wrote:
> > > >
> > > > NOTE: these diagrams may look funny inf NOT viewed with
FIXED-WIDTH
> > > > fonts.
> > > >
> > > > My understanding is that you are trying to write a byte of data
> using
> > > > I2C0 as the master and I2C1 as the slave. If everything worked I
> > would
> > > > expect the I2C transaction to look like this...
> > > >
> > > > START ADDR+W [ACK] DATA [ACK] STOP
> > > >
> > > > ... where brackets "[ ]" are used to indicate that the slave is
> > > > driving SDA (as opposed to the master).
> > > >
> > > > I would expect to see the following I2C0 (master) interrupts and
> > > > states.
> > > >
> > > > START ADDR+W [ACK] DATA [ACK] STOP
> > > > ^ ^ ^
> > > > 0x08 0x18 0x28
> > > >
> > > > Your code for the I2C0 ISR seems to anticipate this sequence
> > > > correctly. One thing I did notice is that in the I2C0 ISR for
state
> > > > 0x18 you do the following...
> > > >
> > > > I2C0DAT = I2C_address; //Send the slave address and the write bit
> > > > I2C0CONCLR = I2C_STA; // Clear the start bit
> > > >
> > > > ... I have them in my code in reverse order...
> > > >
> > > > I2C0CONCLR = I2C_STA; // Clear the start bit
> > > > I2C0DAT = I2C_address; //Send the slave address and the write bit
> > > >
> > > > I don't know that it matters (but you could try it).
> > > >
> > > > I would expect to see the following I2C1 (slave) interrupts and
> > > > states.
> > > >
> > > > START ADDR+W [ACK] DATA [ACK] STOP
> > > > ^ ^ ^
> > > > 0x60 0x80 0xA0
> > > >
> > > > Your code for the I2C1 ISR seems to anticipate this sequence
> > > > correctly. One thing I did notice is that you don't read the
> received
> > > > data in state 0x80 from I2C1DAT. Maybe I2C1 is holding SCL low
(I2C
> > > > wait state) until you do. I'd suggest adding the read of the
> received
> > > > data.
> > > >
> > > > One other thing... I also read I2C1DAT in state 0x60 as a
> diagnostic
> > > > function to see what address (and write/read bit) I received as a
> > > > slave.
> > > >
> > > > TC
> > > >
> > >
>
Hi,

I am a student on a tight budget as you are but I found a good
solution to analyse bitstreams. It is called 'PoScope' by Po.laps.
It is really cheap (99Euro for the basic version) and handles SPI,
I2C, UART, 1Wire and is a poor mans osciloskop (2Ch, 200kHz), 16Ch
Logic-Probe/Generator (8MHz), Spectrum analyzer, etc. as well.

Check it out. http://po.labs.googlepages.com/usbosciloskop

Without debugging equipment you really can waste a lot of time.
Till
--- In l..., "jon.trem" wrote:
>
> I've tried both but it's still not working.
>

Have you looked at your main routine. The last thing it does is to
call I2C_transfer_byte( ). The last line of code in I2C_transfer_byte(
) starts the I2C transaction. At that point execution returns to main
and then what?

Try adding a while(1); as the last line in main, or a delay loop.

TC
It's very strange. When i add while(1); after
I2C_transfer_byte(0x7E,0x30); Nothing happens! No LEDs is on which
means that no START condition has been sent, or whatever. When I have
not while(1) LED1 and LED3 are on.
--- In l..., "tcirobot" wrote:
>
> --- In l..., "jon.trem" wrote:
> >
> > I've tried both but it's still not working.
> > Have you looked at your main routine. The last thing it does is to
> call I2C_transfer_byte( ). The last line of code in I2C_transfer_byte(
> ) starts the I2C transaction. At that point execution returns to main
> and then what?
>
> Try adding a while(1); as the last line in main, or a delay loop.
>
> TC
>