# Making two Arduinos talk over SPI

I'm trying unsuccessfully to make two Arduinos talk using SPI.

I found this great tutorial. The SPI Master send a constant string each second to the SPI Slave, which resends to the USART for depuration purpose. The problem is that nothing is printed on the Arduino's Serial Monitor.

The SPI Master is connected on a second computer and also sends the string to USART. The string arrives at the computer.

I tested all of Arduinos pins that I use and they're working (on both Arduinos).

My setup

• Arduino Leonardo: SPI Master
• Seeeduino: SPI Slave

Leonardo___Seeeduino
(10) SS--------->(10) SS
(11) MOSI------->(11) MOSI
(12) MISO<-------(12) MISO
(13) SCLK------->(13) SCLK

The code used on the SPI MASTER:

#include <SPI.h>

void setup (void)
{
Serial.begin(115200);
digitalWrite(SS, HIGH);
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);
}

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);
Serial.print(c);
}

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

delay (1000);
}


And the code used on the SPI SLAVE:

#include <SPI.h>

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

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

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

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

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

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

// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register
if (pos < sizeof buf)
{
buf [pos++] = c;
if (c == '\n')
process_it = true;
}
}

void loop (void)
{
if (process_it)
{
buf [pos] = 0;
Serial.println (buf);
pos = 0;
process_it = false;
}
}


Is there something wrong on this project? How can I make it work?

-
It sure looks like you're doing everything right. Do you have access to a scope or logic analyzer to observe the activity on the pins? –  Dave Tweed Sep 26 '12 at 21:22
@DaveTweed Unfortunately I don't have a logic analyser, but I do have an OLD oscilloscope: a Minipa's MO-1222. I've tried to use it to solve this problem but I couldn't see any signal. Despite having enough sampling frequency for that, I don't know how to configure it (triggers, etc.) to really get to analyze the signals. –  borges Sep 26 '12 at 21:51
That looks like a pretty decent scope for this sort of thing (20 MHz, dual trace analog). It would be great if you could find someone to sit down with you for an hour or so to show you how to use it; unfortunately, it would be very difficult to do it through a forum like this. It's a skill you'll use throughout your career. –  Dave Tweed Sep 27 '12 at 1:35

I took a quick look at the Arduino SPI library and couldn't find the attachInterrupt() function. I assume that you're using an extended library of some sort and I'll make the assumption that it works although I would like to see how it's implemented underneath.

A couple things that I saw:

1. This compiles? if (pos < sizeof buf) - it probably needs to be if (pos < sizeof(buf))
2. In the sample code on the forum, he has a key line right here that you're missing in your slave code:

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


Without this your receive interrupt probably won't fire. I also don't see where global interrupts are being enabled although I have no idea if Arduino takes care of that for you under the hood. I also haven't bothered to look up what any of those registers mean, I'm trying my best to go by memory of AVR's SPI registers.

-
Incredibly the code compiles! Despite this, I've modified it following your suggestion. About the SPI.attachInterrupt() function, I don't know why it is not documented, but it is implemented as we can see here. It does exactly what you said in the second point. Thank you for your help! It was because of you that could indirectly get the answer. –  borges Sep 27 '12 at 20:30
@borges, cool. If it fixed your problem, feel free to mark your own answer as the accepted answer. –  Jon L Sep 27 '12 at 20:35