That's a good question. I was wondering that too. A little research and I have an example.
Hardware: Connect two Arduinos together with the following pins connected:
10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK)
Also, +5v and GND
Master (the one that sends the data) - upload this test sketch:
#include <SPI.h>
#include "pins_arduino.h"
void setup (void)
{
// 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 ();
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 (the one that receives the data) - upload this test sketch:
#include "pins_arduino.h"
char buf [100];
volatile byte pos;
volatile boolean process_it;
void setup (void)
{
Serial.begin (9600); // debugging
// 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);
pos = 0;
process_it = false;
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;
// add to buffer if room
if (pos < sizeof buf)
{
buf [pos++] = c;
// example: newline means time to process buffer
if (c == '\n')
process_it = true;
} // end of room available
}
// 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
Then fire up the serial monitor on the slave and watch "Hello, world" scroll by.
Points to note:
- The master divides the clock down a bit, otherwise it pushes out data too fast for the slave to process
- The slave is interrupt-driven. Thus it can be doing other stuff until incoming data arrives.