View previous topic :: View next topic |
Author |
Message |
FMOpt2000
Joined: 10 Jan 2008 Posts: 17
|
I2C issue |
Posted: Wed Mar 21, 2012 2:21 am |
|
|
Hi,
I'm working on I2C protocol to connect a Cypress 68013A (MASTER) and a 18LF4525 (SLAVE).
I did a lot of test and now I can read the I2C write operation only with a polling in the main:
Code: |
while(count!=3)
{
while(!i2c_poll()) ;
buffer[count++]= i2c_read(); //Read Next
}
|
So we can assume that the hardware is OK.
But now I have issues in the SSP interrupt
Code: |
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
address = incoming;
if(state == 2) //Second received byte is data
buffer[address] = incoming;
}
if(state == 0x80) //Master is requesting data
{
i2c_write(buffer[address]);
}
}
|
When the I2C write operation is done, with a breakpoint I see that the interrupt is triggered and it's read the address,but the case "state==2"
isn't never triggered.
Why?
Could you help me?
(I took this from ex_slave example.... so it's strange)
What's the meaning of "state"?
1 address
2 first byte
3 second byte etc? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Wed Mar 21, 2012 4:30 am |
|
|
Look again at the example.
State '0x80', is an odd one. On this state you must both _read_ the address byte received, and write back the reply. Failing to do the first, will hang the peripheral.
In I2C, the standard 'packet', is:
Start
Device address number sent (normally with write flag set)
Register address number sent.
Then write to register 'address', address+1 etc., _or_
Issue 'restart'
Send device address number with read flag sent.
Read from register 'address', address+1 etc. (NACK last byte).
Stop
The sequence at your master has to be right. You 'poll' code won't worry if is just keeps receiving address bytes for example. The ISR code will mind....
Best Wishes |
|
|
FMOpt2000
Joined: 10 Jan 2008 Posts: 17
|
|
Posted: Wed Mar 21, 2012 8:17 am |
|
|
Hi,
Now i have solved the single function (READ/WRITE)
Code: |
void ssp_interupt ()
{
BYTE app;
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming=i2c_read();
buffer[state]=incoming;
//index++;
}
if(state == 0x80) //Master is requesting data
{
i2c_write(0xAA);
app=buffer[0];
i2c_write(app);
app=buffer[1];
i2c_write(app);
i2c_write(0x55);
}
}
|
In the buffer I see what I wrote; I read from PIC.
I've only one issue.....
I must reset the pic for every single operation (those are correct).
If I wrote and then do a "read op" the pic hangs up.
In debug , after the write op, I gave the read op and in the "i2c_isr_state()" I've a 0x00 but I'm expecting a 0x80 because it's a reading.
What am I missing? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Wed Mar 21, 2012 4:06 pm |
|
|
You still haven't done what Ttelmah suggested in his first set of sentences. You need to do that. Once you get that done we can further help debug your code, but until you do that, we don't know if that is what is causing your problem or if it is something else.
Also as a note, you don't typically write 4x bytes when the state is 0x80 like you have in your code. It might still work (depends on how the master reacts to that). Take a look at the example in the compiler manual (or help index) for i2c_isr_state(). It gives a simple ISR set of code. I think there is a typo in it like "i@c instead of "i2c" but otherwise should work good. Try modifying that to suit your needs. |
|
|
FMOpt2000
Joined: 10 Jan 2008 Posts: 17
|
|
Posted: Thu Mar 22, 2012 2:07 am |
|
|
Hi, it wasn't clear what Ttelmah said to me.
I didn't modify the Cypress firmware because I was sure the firmware was right (I use these routines with a lot of I2C ICs in my design);
So I supposed the issue was only in the PIC side.
I copy another example of CCS and now I haven't problem.
Herin the code:
Code: |
void i2c_isr() {
BYTE
state;
state = i2c_isr_state();
if(state >= 0x80)
{
i2c_write(rcv_buffer[state - 0x80]);
i2c_write(rcv_buffer[state+1 - 0x80]);
i2c_write(rcv_buffer[state+2 - 0x80]);
i2c_write(rcv_buffer[state+3 - 0x80]);
}
else if(state > 0)
rcv_buffer[state - 1] = i2c_read();
}
|
I don't see particulary differences so I don't understand why now It's right.....
Thx for your support. |
|
|
|