SPI slave receive and return array using SPI.transfer(data,size)

Hi,

I try to do that :

Master send [1,3,6]
Slave increment items and return [2,4,7]

MASTER :

byte datas[3] = {1,3,6};

SPI.transfer(&datas,3); // or SPI.transfer(datas,3);

Serial.println("Master[0] =>"+String(datas[0]));
Serial.println("Master[1] =>"+String(datas[1]));
Serial.println("Master[2] =>"+String(datas[2]));

SLAVE :

volatile byte buff[3];
byte indx;

void loop()
  if (process)
  {
    Serial.println("Slave[0] => "+String(buff[0]));
    Serial.println("Slave[1] => "+String(buff[1]));
    Serial.println("Slave[2] => "+String(buff[2]));
    process=false;
   }
}

ISR (SPI_STC_vect)
{
   byte c = SPDR; // read byte from SPI Data Register
   buff [indx++] = c;

   SPDR = c+1; // return increment
   
   if (c==6) {
    process =true;
   }
}

Slave receives the right datas :
Slave[0] => 1
Slave[1] => 3
Slave[2] => 6

but master return :
Master[0] => 7 (expected 2, but return last item)
Master[1] => 3 (unchanged, expected 4)
Master[2] => 6 (unchanged, expected 7)

What is the solution ?

Best regards,

Vincent

have you tried Nick Gammon's tutorial of SPI communication between arduinos?

does that work OK with your setup?

Yes, it works byte by byte, but i try to use SPI.transfer(array, size) function.

vblocs:
Yes, it works byte by byte, but i try to use SPI.transfer(array, size) function.

one possible reason why that function is not working here is that it is too quick. if you had a look at Nick's example, in the 'transferAndWait' function there is a small delay to give the slave enough time to process.

you could implement a similar function but takes in an array instead; something like this maybe (UNTESTED!):

void transferAndWait (byte *arr, uint8_t size)
{
  uint8_t i = 0;
  byte a = SPI.transfer (arr[i]);
  
  delayMicroseconds (20);
  
  for (i = 0; i < size - 1; ++i) {
    arr[i] = SPI.transfer (arr[i + 1]);
    delayMicroseconds (20);
  }

  arr[i] = SPI.transfer (0x00);

} // end of transferAndWait

hope that helps

Yes, byte by byte works.

SPI.transfer(firstByte);
delayMicroseconds(10);

SPI.transfer(secondByte);
delayMicroseconds(10);
etc...

But, how to use one shot : SPI.transfer(datas,size) and get slave datas ?

I post a very simple example. But in my case, I send command and parameters : [commandType, paramA, paramB]
and slave return values.

vblocs:
Yes, byte by byte works.

SPI.transfer(firstByte);
delayMicroseconds(10);

SPI.transfer(secondByte);
delayMicroseconds(10);
etc...

But, how to use one shot : SPI.transfer(datas,size) and get slave datas ?

I post a very simple example. But in my case, I send command and parameters : [commandType, paramA, paramB]
and slave return values.

I just explained to you why the 'standard' function may not work for your case and provided you with a custom function based on nick's example that would do the the same thing (ie take in an array)....

please try the custom function and see if it works for you!

Thanks.
I try it...