user49676: I have recently been trying to send integers via SPI between two arduino Uno's. I am using the first example of Nick Gammons tutorial, and trying to modify it to get a basic understanding of how to communicate via SPI.
http://www.gammon.com.au/spi
MASTER
// Written by Nick Gammon
// February 2011


#include <SPI.h>

void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}  // end of setup


void loop (void)
{

  char c;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Hello, world!\n" ; c = *p; p++)
    SPI.transfer (c);

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop

SLAVE - WITHOUT INTERRUPTS
// Written by Nick Gammon
// February 2011


#include <SPI.h>

char buf [100];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // get ready for an interrupt 
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos < (sizeof (buf) - 1))
    buf [pos++] = c;

  // example: newline means time to process buffer
  if (c == '\n')
    process_it = true;

}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;  
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set

}  // end of loop

SLAVE - WITH INTERRUPTS 
// Written by Nick Gammon
// April 2011


// what to do with incoming data
byte command = 0;

// start of transaction, no command yet
void ss_falling ()
{
  command = 0;
}  // end of interrupt service routine (ISR) ss_falling

void setup (void)
{

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  // interrupt for SS falling edge
  attachInterrupt (0, ss_falling, FALLING);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;

  switch (command)
  {
  // no command? then this is the command
  case 0:
    command = c;
    SPDR = 0;
    break;

  // add to incoming byte, return result
  case 'a':
    SPDR = c + 15;  // add 15
    break;

  // subtract from incoming byte, return result
  case 's':
    SPDR = c - 8;  // subtract 8
    break;

  } // end of switch

}  // end of interrupt service routine (ISR) SPI_STC_vect


void loop (void)
{
// all done with interrupts
}  // end of loop

ORIGINAL ISSUE - I am able to get this working, so the wiring is correct, however i am unable to get it to send anything other than a string. I can change the string and that works, but i am getting confused with pointers in C. Any code i have tried doesn't compile correctly, or doesn't send at all if it does compile. Could someone give me a clue as to where to start with this. My best effort is below
MASTER
#include <SPI.h>

int x = 10000;
int y = 20000;
int z = 30000;
byte High_x = highByte(x);
byte Low_x = lowByte(x);
byte High_y = highByte(y);
byte Low_y = lowByte(y);
byte High_z = highByte(z);
byte Low_z = lowByte(z);

int X =  word(High_x<<8|Low_x);
int Y =  word(High_y<<8|Low_y);
int Z =  word(High_z<<8|Low_z);

  byte myArray[7];



void setup (void)
{

  Serial.begin(115200);
  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

 myArray[0] = High_x;
 myArray[1] = Low_x; 
 myArray[2] = High_y;
 myArray[3] = Low_y;
 myArray[4] = High_z;
 myArray[5] = Low_z;  
 myArray[6] = 0;

  Serial.println(X);
  Serial.println(Y);
  Serial.println(Z);
  delay(2000);
}

void loop (void)
{

  byte data;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (byte * p =  myArray[0]; data = *p; p++)
    SPI.transfer (data);
    Serial.println("sending data");

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop

SLAVE
#include <SPI.h>

byte buf [100];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // get ready for an interrupt 
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();
Serial.println("End of Setup");
}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  Serial.println("Beginning of Interrupt Routine");
byte data = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos < (sizeof (buf) - 1))
    buf [pos++] = data;

  // example: newline means time to process buffer
  if (data == '0')
    process_it = true;
      Serial.println("End of Interrupt Routine");
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
    Serial.println("Beggining of Loop");

  for(int i = 0; i < 100; i++)
  if (process_it)
    {
    buf [pos] = 0;  
    Serial.println (buf[i]);
    pos = 0;
    process_it = false;
    }  // end of flag set
    Serial.println("End of Loop");
}  // end of loop

In the future i hope to send 10 16-bit integers over SPI from an arduino to an arduino or maybe arduino to a raspberry Pi. 
Thanks
EDIT -I have started using the code that uses interrupts and managed to get the data i need sent across, however, i can only get the correct data by setting both the first and second element of the array to "High_x", otherwise it skips the first part of data?
NEW MASTER
#include <SPI.h>

int x = 10000;
int y = 20000;
int z = 30000;
byte High_x = highByte(x);
byte Low_x = lowByte(x);
byte High_y = highByte(y);
byte Low_y = lowByte(y);
byte High_z = highByte(z);
byte Low_z = lowByte(z);

int X =  word(High_x<<8|Low_x);
int Y =  word(High_y<<8|Low_y);
int Z =  word(High_z<<8|Low_z);

  byte myArray[8];



void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

 myArray[0] = High_x;
 myArray[1] = High_x;
 myArray[2] = Low_x; 
 myArray[3] = High_y;
 myArray[4] = Low_y;
 myArray[5] = High_z;
 myArray[6] = Low_z;  
 myArray[7] = 0;

  Serial.print("wait for loop");
  //Serial.println(X);
  //Serial.println(Y);
  //Serial.println(Z);
  delay(2000);
}

void loop (void)
{

  byte data;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (byte * p =  &myArray[0]; data = *p; p++){
    SPI.transfer (data);
  }
  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop

NEW SLAVE
byte buf [100];
volatile byte pos;
// what to do with incoming data
byte command = 0;

// start of transaction, no command yet
void ss_falling ()
{
  command = 0;
}  // end of interrupt service routine (ISR) ss_falling

void setup (void)
{

  Serial.begin(9600);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  // interrupt for SS falling edge
  attachInterrupt (0, ss_falling, FALLING);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte data = SPDR;

  // add to buffer if room
  if (pos < (sizeof (buf) - 1))
    buf [pos++] = data;

}  // end of interrupt service routine (ISR) SPI_STC_vect


void loop (void)
{

  for(int i = 0; i < 100; i++){


    Serial.println (buf[i]);
    pos = 0;
    delay(1000);
  }
}  // end of loop

Any suggestions on why this is necessary? Is there some basic SPI idiosyncrasy I'm missing?
Thanks all
Ross

user614: You have a couple of issues going on here.
First of all, Nick Gammon's example is transmitting strings. Strings have the property that a particular value, '\0' (null), cannot normally appear in the string itself, and it can therefore be used as an "end flag" to mark the end of the string. This is why the for loop on the master side works correctly.
Note that the null itself is NOT transmitted over the SPI link. Instead, Nick shows an example of using another character ('\n' - newline) to trigger processing on the slave side.
If you want to transmit binary data, which could easily contain bytes of 0x00 (null), you need to find a different way to delimit the data on both the sending side and the receiving side. Your example data (16-bit integers of 10000, 20000 and 30000) doesn't contain any null bytes, but you can't rely on that in general. Also, because the null doesn't actually get transmitted, you can't use it on the receiving side to trigger processing.
There are a couple of approaches that are frequently used to send binary data:

Send the number of bytes explicitly at the beginning of the transaction, and trigger receive-side processing once that number of bytes has been received.
Use a "special" value (e.g., null) to mark the end of the data, but then you have to "escape" that value in some way if it ever appears in the actual data.


In addition to all of that, you have a bug on your master side code. The initialization of your for loop, byte * p =  myArray[0] does not set the pointer p to the address of myArray as intended; instead, it sets it to the value of the first byte in the array, which is 0x27 (High_x). You need to say either byte * p =  &myArray[0] or simply byte * p =  myArray.

user-1: I can see two big problems at your code (there could be more, but i didnt look that hard). 
First is using Serial.println in interrupt routine. This prevent receiving of more than one byte as Serial.println will take much more time to execute than receiving 6 bytes (even on slow SPI clock) on SPI. In most cases Interrupt routines should finish fast.
Next problem is that you are testing for char 0 ('0') which is not equal to byte 0 you are sending as end of data, but has value of 48 in decimal.   
Edit for how to test for end of data:
You can test for end of that few different ways, having fixed number of byte transfers, setting interrupt on slave select pin or encode data binary data in base64 and use control char. I would recommend interrupt.

49676: <p>I have recently been trying to send integers via SPI between two arduino Uno's. I am using the first example of Nick Gammons tutorial, and trying to modify it to get a basic understanding of how to communicate via SPI.</p>

<p><a href="http://www.gammon.com.au/spi" rel="nofollow noreferrer">http://www.gammon.com.au/spi</a></p>

<p>MASTER</p>

<pre><code>// Written by Nick Gammon
// February 2011


#include &lt;SPI.h&gt;

void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}  // end of setup


void loop (void)
{

  char c;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Hello, world!\n" ; c = *p; p++)
    SPI.transfer (c);

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop
</code></pre>

<p>SLAVE - WITHOUT INTERRUPTS</p>

<pre><code>// Written by Nick Gammon
// February 2011


#include &lt;SPI.h&gt;

char buf [100];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // get ready for an interrupt 
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos &lt; (sizeof (buf) - 1))
    buf [pos++] = c;

  // example: newline means time to process buffer
  if (c == '\n')
    process_it = true;

}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;  
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set

}  // end of loop
</code></pre>

<p>SLAVE - WITH INTERRUPTS </p>

<pre><code>// Written by Nick Gammon
// April 2011


// what to do with incoming data
byte command = 0;

// start of transaction, no command yet
void ss_falling ()
{
  command = 0;
}  // end of interrupt service routine (ISR) ss_falling

void setup (void)
{

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  // interrupt for SS falling edge
  attachInterrupt (0, ss_falling, FALLING);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;

  switch (command)
  {
  // no command? then this is the command
  case 0:
    command = c;
    SPDR = 0;
    break;

  // add to incoming byte, return result
  case 'a':
    SPDR = c + 15;  // add 15
    break;

  // subtract from incoming byte, return result
  case 's':
    SPDR = c - 8;  // subtract 8
    break;

  } // end of switch

}  // end of interrupt service routine (ISR) SPI_STC_vect


void loop (void)
{
// all done with interrupts
}  // end of loop
</code></pre>

<p>ORIGINAL ISSUE - I am able to get this working, so the wiring is correct, however i am unable to get it to send anything other than a string. I can change the string and that works, but i am getting confused with pointers in C. Any code i have tried doesn't compile correctly, or doesn't send at all if it does compile. Could someone give me a clue as to where to start with this. My best effort is below</p>

<p>MASTER</p>

<pre><code>#include &lt;SPI.h&gt;

int x = 10000;
int y = 20000;
int z = 30000;
byte High_x = highByte(x);
byte Low_x = lowByte(x);
byte High_y = highByte(y);
byte Low_y = lowByte(y);
byte High_z = highByte(z);
byte Low_z = lowByte(z);

int X =  word(High_x&lt;&lt;8|Low_x);
int Y =  word(High_y&lt;&lt;8|Low_y);
int Z =  word(High_z&lt;&lt;8|Low_z);

  byte myArray[7];



void setup (void)
{

  Serial.begin(115200);
  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

 myArray[0] = High_x;
 myArray[1] = Low_x; 
 myArray[2] = High_y;
 myArray[3] = Low_y;
 myArray[4] = High_z;
 myArray[5] = Low_z;  
 myArray[6] = 0;

  Serial.println(X);
  Serial.println(Y);
  Serial.println(Z);
  delay(2000);
}

void loop (void)
{

  byte data;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (byte * p =  myArray[0]; data = *p; p++)
    SPI.transfer (data);
    Serial.println("sending data");

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop
</code></pre>

<p>SLAVE</p>

<pre><code>#include &lt;SPI.h&gt;

byte buf [100];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // get ready for an interrupt 
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();
Serial.println("End of Setup");
}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  Serial.println("Beginning of Interrupt Routine");
byte data = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos &lt; (sizeof (buf) - 1))
    buf [pos++] = data;

  // example: newline means time to process buffer
  if (data == '0')
    process_it = true;
      Serial.println("End of Interrupt Routine");
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
    Serial.println("Beggining of Loop");

  for(int i = 0; i &lt; 100; i++)
  if (process_it)
    {
    buf [pos] = 0;  
    Serial.println (buf[i]);
    pos = 0;
    process_it = false;
    }  // end of flag set
    Serial.println("End of Loop");
}  // end of loop
</code></pre>

<p>In the future i hope to send 10 16-bit integers over SPI from an arduino to an arduino or maybe arduino to a raspberry Pi. </p>

<p>Thanks</p>

<p>EDIT -I have started using the code that uses interrupts and managed to get the data i need sent across, however, i can only get the correct data by setting both the first and second element of the array to "High_x", otherwise it skips the first part of data?</p>

<p>NEW MASTER</p>

<pre><code>#include &lt;SPI.h&gt;

int x = 10000;
int y = 20000;
int z = 30000;
byte High_x = highByte(x);
byte Low_x = lowByte(x);
byte High_y = highByte(y);
byte Low_y = lowByte(y);
byte High_z = highByte(z);
byte Low_z = lowByte(z);

int X =  word(High_x&lt;&lt;8|Low_x);
int Y =  word(High_y&lt;&lt;8|Low_y);
int Z =  word(High_z&lt;&lt;8|Low_z);

  byte myArray[8];



void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

 myArray[0] = High_x;
 myArray[1] = High_x;
 myArray[2] = Low_x; 
 myArray[3] = High_y;
 myArray[4] = Low_y;
 myArray[5] = High_z;
 myArray[6] = Low_z;  
 myArray[7] = 0;

  Serial.print("wait for loop");
  //Serial.println(X);
  //Serial.println(Y);
  //Serial.println(Z);
  delay(2000);
}

void loop (void)
{

  byte data;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (byte * p =  &amp;myArray[0]; data = *p; p++){
    SPI.transfer (data);
  }
  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop
</code></pre>

<p>NEW SLAVE</p>

<pre><code>byte buf [100];
volatile byte pos;
// what to do with incoming data
byte command = 0;

// start of transaction, no command yet
void ss_falling ()
{
  command = 0;
}  // end of interrupt service routine (ISR) ss_falling

void setup (void)
{

  Serial.begin(9600);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  // interrupt for SS falling edge
  attachInterrupt (0, ss_falling, FALLING);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte data = SPDR;

  // add to buffer if room
  if (pos &lt; (sizeof (buf) - 1))
    buf [pos++] = data;

}  // end of interrupt service routine (ISR) SPI_STC_vect


void loop (void)
{

  for(int i = 0; i &lt; 100; i++){


    Serial.println (buf[i]);
    pos = 0;
    delay(1000);
  }
}  // end of loop
</code></pre>

<p>Any suggestions on why this is necessary? Is there some basic SPI idiosyncrasy I'm missing?</p>

<p>Thanks all</p>

<p>Ross</p>
 614: <p>You have a couple of issues going on here.</p>

<p>First of all, Nick Gammon's example is transmitting strings. Strings have the property that a particular value, <code>'\0'</code> (null), cannot normally appear in the string itself, and it can therefore be used as an "end flag" to mark the end of the string. This is why the <code>for</code> loop on the master side works correctly.</p>

<p>Note that the null itself is NOT transmitted over the SPI link. Instead, Nick shows an example of using another character (<code>'\n'</code> - newline) to trigger processing on the slave side.</p>

<p>If you want to transmit binary data, which could easily contain bytes of 0x00 (null), you need to find a different way to delimit the data on both the sending side and the receiving side. Your example data (16-bit integers of 10000, 20000 and 30000) doesn't contain any null bytes, but you can't rely on that in general. Also, because the null doesn't actually get transmitted, you can't use it on the receiving side to trigger processing.</p>

<p>There are a couple of approaches that are frequently used to send binary data:</p>

<ul>
<li><p>Send the number of bytes explicitly at the beginning of the transaction, and trigger receive-side processing once that number of bytes has been received.</p></li>
<li><p>Use a "special" value (e.g., null) to mark the end of the data, but then you have to "escape" that value in some way if it ever appears in the actual data.</p></li>
</ul>

<hr>

<p>In addition to all of that, you have a bug on your master side code. The initialization of your <code>for</code> loop, <code>byte * p =  myArray[0]</code> does not set the pointer <code>p</code> to the address of <code>myArray</code> as intended; instead, it sets it to the value of the first byte in the array, which is 0x27 (<code>High_x</code>). You need to say either <code>byte * p =  &amp;myArray[0]</code> or simply <code>byte * p =  myArray</code>.</p>
 -1: <p>I can see two big problems at your code (there could be more, but i didnt look that hard). </p>

<p>First is using Serial.println in interrupt routine. This prevent receiving of more than one byte as Serial.println will take much more time to execute than receiving 6 bytes (even on slow SPI clock) on SPI. In most cases Interrupt routines should finish fast.</p>

<p>Next problem is that you are testing for char 0 ('0') which is not equal to byte 0 you are sending as end of data, but has value of 48 in decimal.   </p>

<p>Edit for how to test for end of data:</p>

<p>You can test for end of that few different ways, having fixed number of byte transfers, setting interrupt on slave select pin or encode data binary data in base64 and use control char. I would recommend interrupt.</p>
