Electronic – arduino – Making two Arduinos talk over SPI

arduinoavrspi

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

setup

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?

Best Answer

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.