Go Down

Topic: Arduino as SPI slave (Read 7 times) previous topic - next topic

Nick Gammon

May 10, 2011, 12:02 am Last Edit: May 10, 2011, 12:04 am by Nick Gammon Reason: 1

... does the SCK continually send a pulse?

No it doesn't. See my logical analyzer data here:


However, it is important to note that SPI does not wait for any acknowledgement. So if you are the slave, and you are not processing the data, that's your bad luck. The master will keep sending it.

... or does this indicate the SPI is pumping data out were just not seeing it?

Sounds like it is doing just that.

Sounds like either you have not configured your end as a slave, you haven't pulled SS low, or your interrupt service routine is not firing for some reason (like interrupts disabled).


May 11, 2011, 10:47 pm Last Edit: May 11, 2011, 10:53 pm by nathanBomberHarris Reason: 1
Hello Nick/Rob

This is odd after studying the ARDUINO 2009 sckematic I copied the 1K resistor and LED L off the SCK PIN and did the same on my breadboard for PIN 11 boths pins flash away nicely!

I take it that this means SPI data must be traversing the connections but still no output on the seriasl monitor window????

Help! I feel its nearly there what I am I missing (PIN 10 to gnd)


Nick Gammon

Can we see the sketch for the receiving end?


Sure //note code added as suggested by Rob I tried with and without :) thank you for helping

// Written by Nick Gammon
// February 2011

#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);
  // get ready for an interrupt
  pos = 0;   // buffer empty
  process_it = false;

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

}  // 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)
    buf [pos++] = c;
    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;
    }  // end of room available
}  // 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; 
    for (int i = 0; i < 100; i++)// Code added on suggestion Rob
    Serial.println (buf[0],HEX); // Code added on suggestion Rob
    pos = 0;
    process_it = false;
    }  // end of flag set
}  // end of loop

Nick Gammon

It helps to use the [ code ] tags (hit the # button above the post).

Anyway, you won't see anything if process_it is not true, and that hinges on getting a newline. Does the device send one?

For debugging you could change it to something like this to see if the buffer is filling up:

Code: [Select]
void loop (void)

  // debugging 
  if (pos > 20)
   for (int i = 0; i < pos; i++)
      Serial.println (buf[i], HEX);
      pos = 0;
}  // end of loop

Go Up