|
|
View previous topic :: View next topic |
Author |
Message |
rcooke
Joined: 23 Feb 2011 Posts: 21 Location: Oceanside, CA USA
|
SPI interrupt behavior - is this possible? |
Posted: Mon Mar 21, 2011 3:24 pm |
|
|
Hi Folks,
Does the #INT_SSP interrupt fire at the beginning of SPI activity or does it fire after one byte is received? I need to be able to read 3 bytes as fast as possible.
In my application a master controller (off board) will send my PIC18F24K22 3 bytes. 1st byte is the command byte, 2nd byte is the data byte and the 3rd is a dummy (all zeroes). My slave has to send a sync byte (0x5a) as it's receiving the command byte, echos the command byte and then sends the requested data byte.
I was going to do something like this:
Code: |
#int_ssp
void ssp_isr(void)
{
int8 dummy;
Command_Byte = spi_read(SYNC_BYTE); // slave must send the sync byte as 1st byte
Data_Byte = spi_read(Command_Byte); // slave must echo the command byte back to master
switch(Command_Byte) {
case 0xA8: // read of supply_control register
dummy = spi_read(Supply_Control_Reg);
break;
case 0xA9: // read of supply fault register
dummy = spi_read(Supply_Fault_Reg);
break;
default:
dummy = spi_read(0xaa);
}
|
I'm assuming that I can read all 3 bytes while in the ISR.
Thanks,
Richard |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Mar 21, 2011 3:48 pm |
|
|
Look in the 18F24K22 data sheet in the SPI slave section:
http://ww1.microchip.com/downloads/en/DeviceDoc/41412D.pdf
It says:
Quote: |
Once the 8 bits of data have been received, that byte is moved to
the SSPxBUF register. Then, the Buffer Full Detect bit, BF of the
SSPxSTAT register, and the interrupt flag bit, SSPxIF, are set.
This double-buffering of the received data (SSPxBUF) allows the
next byte to start reception before reading the data that was just
received.
When the SSPxBUF is read, the BF bit is cleared.
|
That's one interrupt per byte.
However, if you know that you are going to receive multiple bytes
with very little delay between them, you could poll the BF bit while
still inside the isr and read multiple bytes. However, for safety,
you should have some kind of timeout mechanism, so you don't
have your program get stuck in the isr. Maybe the WDT could be
used for this. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Mar 21, 2011 3:49 pm |
|
|
To 'send a sync byte as it is receiving the command byte', you would need to 'preload' this _before the transaction_. So load it once before starting the SPI interrupt, and reload it at the end of the interrupt. You can't 'send' bytes with the SPI read on the slave.
Basically, you get an INT_SSP, when a byte is ready for you to read. At this point, the byte that was in the output shift register has _already_ been sent to the master.
What you show can potentially work, _but_ there needs to be time for the PIC to actually get into the SPI code, _before_ the second transaction completes from the master. So, if (for example), the SPI is being clocked at 4MHz, and the bytes were sent genuinely without break, you only have 2uSec to actually get into the SPI interrupt routine. The PIC typically takes about 30 instructions to get into it's interrupt handler, and another half dozen to read a byte and load the output register, so say 40 instruction times, which would imply an 80MHz master clock, to handle the data at this speed. There are PICs that can do this speed, or your data needs to be slower....
Code: |
//In main
spi_write(SYNC_BYTE); //preload the sync byte
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
//Then for the SPI handler
#int_ssp
void ssp_isr(void)
{
Command_Byte = spi_read(); // sync byte has _already_ been sent
spi_write(Command_byte);
while !(spi_data_is_in()) ; //Consider a timeout here
Data_Byte = spi_read(); // Command byte _has_ been sent once you
//receive this
//Load the replies
switch(Command_Byte) {
case 0xA8: // read of supply_control register
spi_write(Supply_Control_Reg);
break;
case 0xA9: // read of supply fault register
spi_write(Supply_Fault_Reg);
break;
default:
spi_write(0xaa);
}
//Now wait for the transaction to complete
while !(spi_data_is_in()) ; //Again consider a timeout here
//Now reload the sync byte waiting for the next transfer
spi_write(SYNC_BYTE);
}
|
Slave SPI, is 'back to front'. You have to send the byte for a transaction, _before_ the transaction occurs. Provided your rate is low enough, that you can get around 40 instruction times or slightly more, in the time that a byte takes to arrive, this should work.
Best Wishes |
|
|
|
|
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
|