Spi interrupt code

microchipmicrocontrollerpicspi

I am trying to let two uC talk to each other. Both chips are from dsPIC33EP family. The slave will respond according to what master has sent to it. My question is, since SPI is full-duplex, would it be too late to send data back to master in one communication cycle? Should I load one byte to transmit buffer before receiving one byte? Please see my code as I demonstrate my doubts.

void ISR() iv IVT_ADDR_SPIINTERRUPT{
    char data;
    SpiIntFlag=0;//clear interrupt flag
    data=SPIBUF;//read the incoming byte

    //send back one byte according to the received byte
    if(data==0x01){
        SPIBUF=0xF1;
    }
    else if(data==0x02){
        SPIBUF=0xF2;
    }
    else if(data==0x03){
        SPIBUF=0xF3;
    }
    else if(data==0x04){
        SPIBUF=0xF4;
    }

}

As you can see, a byte will be sent after the slave receives one.
Does it mean receiving and sending do not happen at the same time?
I have tried this code with ATmega32u4 at 5MHZ. But it looks like the master receives a corresponding byte according to the byte sent to the slave. Also, there is no additional bytes received so I think this communication process(read and send) happen at the same time. What about the delay that if() statements caused?

Is this the correct way to do SPI communication? All I want to achieve is master send one command byte and slave send back couple bytes back according to it.

Best Answer

With SPI the master generates the clock so there's not really a concept of being able to receive multiple bytes back from a slave automatically, you have to send additional dummy bytes to generate the clock. Say if you had a sensor and you wanted command 0x01 to send back the current temperature the pseudo-code for the master may look like:

spi_write(0x01);
t_lsb = spi_write(0x00); // These dummy bytes are just needed to generate a clock
t_msb = spi_write(0x00); // So that the slave gets a chance to send the results back

On and the slave it might look like:

cmd = spi_read();
if (cmd == 0x01) {
  spi_write(t_lsb);
  spi_write(t_msb);
}

You can technically send back a byte from the slave for each byte sent from the master, but for most protocols there probably isn't anything useful to send back until the slave has received and decoded the command. Hopefully you can understand that pseudo-code and the general concept OK, it's been a while since I've programmed PIC SPI at the register level but it sounds like you're on top of that side of things.