View previous topic :: View next topic |
Author |
Message |
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
How can a slave determine the end of the I2C transaction? |
Posted: Wed Apr 09, 2008 2:58 am |
|
|
Colleagues,
Slave PIC is receiving a handful of different commands from the master. Commands have parameters that are transmitted with them, and different commands have different amount of parameters (different number of bytes). The slave needs to trigger the execution of the command as soon as command+parameters are received. SSP hardware causes an interrupt on each byte. Is it legal to sample the SDA and SCL lines at the end of the SSP ISR? For example (I’m trying this code as I write this post):
Code: |
#INT_SSP
void ssp_interupt()
{
iI2Cstate = i2c_isr_state();
if (0 < iI2Cstate && iI2Cstate < 0x80)
{
g_sI2Cin.buff[i] = i2c_read();
if (input(SDA) && input(SCL)) // End?
g_iFlag = 1; // main() has a fast loop. It will quickly pick up this flag and execute the command
}
// ...
} |
P.S. I already see a problem. By the time the SSP ISR is complete, the original transaction could be over, but the new one was started, and both I2C lines are not high. Is there another way (except transmitting the lengths or hard-coding it into the slave)? _________________ Read the label, before opening a can of worms. |
|
|
Matro Guest
|
|
Posted: Wed Apr 09, 2008 3:14 am |
|
|
Look if the stop bit of SSPSTAT register is set.
But I think that is better to put in the code the length of each command for checking purpose.
Matro |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
|
Posted: Wed Apr 09, 2008 3:30 am |
|
|
Matro wrote: | Look if the stop bit of SSPSTAT register is set. |
Thanks, Matro! Checking the bit definitely sounds like less of a hack, than sampling the SCL and SDA.
Out of curiosity. There’s a function i2c_isr_state(), which returns a byte. The MSbit behaves like a R/W# bit of the SSPSTAT. The lower 7 bits behave like a counter, which increments with each byte received or sent. Does this counter exist in hardware or software?
Matro wrote: | But I think that is better to put in the code the length of each command for checking purpose. |
I know, but I want to keep the length of the command to a minimum. _________________ Read the label, before opening a can of worms. |
|
|
Matro Guest
|
|
Posted: Wed Apr 09, 2008 3:47 am |
|
|
kender wrote: | Matro wrote: | Look if the stop bit of SSPSTAT register is set. |
Thanks, Matro! Checking the bit definitely sounds like less of a hack, than sampling the SCL and SDA.
Out of curiosity. There’s a function i2c_isr_state(), which returns a byte. The MSbit behaves like a R/W# bit of the SSPSTAT. The lower 7 bits behave like a counter, which increments with each byte received or sent. Does this counter exist in hardware or software?
|
The counter is purely software and is generated by the CCS "i2c_isr_state()" function.
Quote: |
Matro wrote: | But I think that is better to put in the code the length of each command for checking purpose. |
I know, but I want to keep the length of the command to a minimum. |
The classical way is just to store data in an array and set/clear a flag in the isr. Then data processing is done in the main() function. ;-)
CCS i2c isr generation sometimes causes troubles because the interrupt flag is cleared when isr exits. You can avoid that by coding your isr like that:
Code: |
#int_SSP NOCLEAR
void i2c_isr(void)
{
clear_interrupt(int_SSP);
//code continues
}
|
Matro.[/code] |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
|
Posted: Wed Apr 09, 2008 4:04 am |
|
|
Matro wrote: | Code: |
#int_SSP NOCLEAR
void i2c_isr(void)
{
clear_interrupt(int_SSP);
//code continues
}
|
|
I didn’t realize that such a tight control over the interrupt flag is possible.
Is it possible to receive the whole I2C transaction with just one interrupt? The interrupt would occur when the address is received, then the bytes are read in the loop until the stop condition. Just thinking outloud. _________________ Read the label, before opening a can of worms. |
|
|
Matro Guest
|
|
Posted: Wed Apr 09, 2008 4:15 am |
|
|
kender wrote: | Matro wrote: | Code: |
#int_SSP NOCLEAR
void i2c_isr(void)
{
clear_interrupt(int_SSP);
//code continues
}
|
|
I didn’t realize that such a tight control over the interrupt flag is possible.
Is it possible to receive the whole I2C transaction with just one interrupt? The interrupt would occur when the address is received, then the bytes are read in the loop until the stop condition. Just thinking outloud. |
That's possible but I don't think it's the way to do because with such a way all code execution will be locked during i2c receiving. Neither the main application nor other interrupt(s) can execute during the time you are waiting for the stop condition.
Matro. |
|
|
|