|
|
View previous topic :: View next topic |
Author |
Message |
davefromnj
Joined: 03 May 2007 Posts: 42
|
Question about I2C between pics and SSP Interrupt blocking |
Posted: Thu Oct 30, 2008 4:03 pm |
|
|
SO TO SUM UP:
I HAVE to respond to an input within 2msec. My SSP on my slave device takes about 25mSec in its SSP_ISR to respond.
What ideas do you have to get around this so that even if the slave PIC is in the middle of its 25mSec response, I can poll the input pin within 2mSec and not miss it changing state?
Hello All,
I have a question for you:
I have a PIC18F65J10 which works perfectly with a PIC18F44J10 using I2C except for one problem:
Whenever the PIC18F65J10 asks the PIC18F44J10 for data, the ISR() on the PIC18F44J10 takes too long to respond, too long being about 25mSeconds to send 1 byte of data. The 25mSeconds isn't really the problem--the problem is that I must react within 4mSec to an input pin going high. When the SSP gets pinged, the main program loop gets blocked and because the response takes 25mSec, I miss my input pulse sometimes.
The PIC18F65J10 uses the software I2C on the hardware pins (not using the force_hw.)
The PIC18F44J10 is set to be a slave and is using the SSP_isr().
Is there a way that I can have the PIC18F44J10 NOT use the SSP_isr() and still get my data back to the PIC18F65J10?
My problem is that the ssp_isr() is interrupting my main routine which polls an I/O pin.
The I/O pin timing is critical and the PIC18F44J10 must respond to it within 1-2msec, the i2c timing is not critical at all and can take whole seconds to pass data.
can I do something like:
Code: |
unsigned int address = 0x80;
unsigned int data = 0xFF;
unsigned int temp;
BOOLEAN one_msec_flag = FALSE;
#INT_TIMER0
void timer0_isr()
{ //when this expires 1 millisecond has passed
one_msec_flag = TRUE;
}
#INT_SSP
void i2c_isr()
{
temp = i2c_isr_state();
}
while(1)
{
if (one_msec_flag)
{
task_scheduler();
}
}
void task_scheduler(void)
{
//THIS CHECKING OF INPUT B2 IS TIME CRITICAL.
if(input(PIN_B2))
{
output_bit(PIN_D1, 0);
}
else
{
output_bit(PIN_D1, 1);
}
//THIS DATA RESPONSE TO THE MASTER IS NOT TIME CRITICAL
if (i2c_poll())
{ //if we have been asked for data, respond.
if (temp == address)
{ //our address has been pinged and the master wants a data response
i2c_write(data);
}
}
one_msec_flag = FALSE;
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Thu Oct 30, 2008 4:29 pm |
|
|
Are you sure you mean mSec, not uSec?....
Don't call an ISR at all. Assuming you do mean 'uSec', probably 50% of the time involved, is actually getting into, and out of the ISR, not what you are doing inside it.
You will need to enable the option on the slave I2C, to implement 'clock stretching'. Look in the data sheet, I don't know how this is done in the 65J chip. Then have the I2C interrupt _disabled_, and in the main loop, as often as you can, poll the interrupt flag, at times when you are going to be able to service it. When it sets, call your 'handler' for the I2C.
The clock stretching option, means the I2C transaction will be 'held', pending service.
Best Wishes |
|
|
davefromnj
Joined: 03 May 2007 Posts: 42
|
|
Posted: Thu Oct 30, 2008 4:34 pm |
|
|
Ttelmah wrote: | Are you sure you mean mSec, not uSec?....
Don't call an ISR at all. Assuming you do mean 'uSec', probably 50% of the time involved, is actually getting into, and out of the ISR, not what you are doing inside it.
You will need to enable the option on the slave I2C, to implement 'clock stretching'. Look in the data sheet, I don't know how this is done in the 65J chip. Then have the I2C interrupt _disabled_, and in the main loop, as often as you can, poll the interrupt flag, at times when you are going to be able to service it. When it sets, call your 'handler' for the I2C.
The clock stretching option, means the I2C transaction will be 'held', pending service.
Best Wishes |
Sadly... I mean mSec.
If I issue a command that gets ACK'd to the Slave ISR lasts for about 20uSeconds.
If I issue a command to request data, the Slave ISR lasts for 25mSeconds.
The master unit is using the software I2C on the hardware I2C pins.
The slave unit is using the hardware I2C and the SSP_ISR. |
|
|
davefromnj
Joined: 03 May 2007 Posts: 42
|
|
Posted: Thu Oct 30, 2008 4:41 pm |
|
|
Ttelmah wrote: | Are you sure you mean mSec, not uSec?....
Don't call an ISR at all. Assuming you do mean 'uSec', probably 50% of the time involved, is actually getting into, and out of the ISR, not what you are doing inside it.
You will need to enable the option on the slave I2C, to implement 'clock stretching'. Look in the data sheet, I don't know how this is done in the 65J chip. Then have the I2C interrupt _disabled_, and in the main loop, as often as you can, poll the interrupt flag, at times when you are going to be able to service it. When it sets, call your 'handler' for the I2C.
The clock stretching option, means the I2C transaction will be 'held', pending service.
Best Wishes |
I get what you're saying, but doesn't that mean that the Master unit is now locked (stuck in its I2C_ISR) until the slave lets go of the clock pin?
Or since the master is using the software I2C, will it's own timers expire appropriately---
Basically, one pin on the master and slave will get toggled potentially at random, for 2 msec. Both the master and slave PICs must respond to it.
However, the Master also needs to get the status of the slave, and to send it other commands.
Sending commands only ties up the slave's ISR for about 20uSeconds.
Asking it for data takes like 25mSec.
But BOTH the master PIC and slave PIC must respond to the timecritical input pin. |
|
|
davefromnj
Joined: 03 May 2007 Posts: 42
|
i2C_POLL() |
Posted: Thu Nov 13, 2008 10:02 am |
|
|
hello all,
I am having some trouble with the i2c_poll() funciton.
I don't want to use the SSP_ISR because it ties up my slave processor too long.
So I wrote a really quick slave routine that looks like:
Code: |
// The master sends the following, once per second:
i2c_start();
i2c_write(0xA2);
i2c_write(0x22); //This is a command asking the slave for status.
i2c_start();
i2c_write(0xA3);
test_byte = i2c_read();
i2c_stop();
// Note, I have not enabled the I2C interrupts because I don't want to use them on the slave.
//The slave Address is 0xA2.
while(1)
{
test_func();
}
void test_func(void)
{
int test_dat = 0;
CKP = 1;
if (i2c_poll())
{
test_dat = i2c_read();
if (test_dat == 0xA3)
{
printf("0xA3 \r\n");
printf("R/w = %X \r\n", RW);
printf("D/A = %X \r\n", DA);
i2c_write(0x00);
i2c_stop();
}
else if (test_dat == 0xA2)
{
printf("0xA2 \r\n");
printf("R/w = %X \r\n", RW);
printf("D/A = %X \r\n", DA);
}
else
{
}
|
Can anyone tell me why the R/W bit in the SSPxSTAT always reads "0" and so does the D/A bit?
Shouldn't the D/A bit change state when i2c_poll() returns 0xA2, or 0xA3?
Shouldn't the R/W bit change state?
What am I missing?[/code] |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 13, 2008 10:15 am |
|
|
Quote: | // The master sends the following, once per second:
i2c_start();
i2c_write(0xA2);
i2c_write(0x22); //This is a command asking the slave for status.
i2c_start();
i2c_write(0xA3);
test_byte = i2c_read();
i2c_stop(); |
You must do a 'NAK' on the last read. It's part of the i2c spec.
Add a 0 parameter to that call. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|