CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SPI interrupt behavior - is this possible?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rcooke



Joined: 23 Feb 2011
Posts: 21
Location: Oceanside, CA USA

View user's profile Send private message

SPI interrupt behavior - is this possible?
PostPosted: Mon Mar 21, 2011 3:24 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Mar 21, 2011 3:48 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Mar 21, 2011 3:49 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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