Skip to content

The Awesomeness of SPI

August 22, 2012

SPI is the Serial Peripheral Interface protocol, it’s meant for fairly high speed communication between neighbouring chips or boards.  I’ve used it with arduino, for example, to write to an LCD or to read a real time clock.  It works by having one partner, the Master, supply clocking and control signals.  The other partners, Slaves, use the master’s clock.  This is ideal for the olduino because the 1802 can take its time about getting signals set up before it clocks and the Slaves just wait.  The Olduino Master always talks on one line(called MOSI) and the slaves all talk on another line(MISO).  The Olduino controls which Slave is paying attention with Slave Select lines(SS) – one per Slave.

I’ve had the olduino working to drive a Nokia LCD via SPI, and today I got it to drive an AVR processor slave.  I’m posting this just as an interim and to see how posting c code works. (that’s a bit of a struggle but i guess these are ok). These are both definitely prrof-of-concept. I need to reorganize and generalize the olduino spi code and build some device specific wrappers.

The Olduino code looked like

void main(){
#define SS 0 //olduino pin 0 is slave select for arduino
//using lcddata as MOSI on pin 7 and lcdclk as clock on pin 4

digitalWrite(SS,HIGH); //make sure avr is not selected for now
delay(5000); //let me get the slave set up

    digitalWrite(SS,LOW); //select the avr
    shiftOut('H'); shiftOut('e'); shiftOut('l'); shiftOut('l'); shiftOut('o'); shiftOut('!'); shiftOut('*');
    digitalWrite(SS,HIGH); //deselect the avr

and the arduino code looked like this

// Written by Nick Gammon
// February 2011
#define MISO 12
#include <SPI.h>

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

void setup (void){
  Serial.begin (57600); // debugging
  Serial.println("SPI slave here!");
  pinMode(MISO, OUTPUT); // have to send on master in, *slave out*
  SPCR |= _BV(SPE); // turn on SPI in slave mode
  // get ready for an interrupt
  pos = 0; // buffer empty
  process_it = false;
  SPI.attachInterrupt();// now turn on interrupts
} // end of setup

ISR (SPI_STC_vect) // SPI interrupt routine{
  byte c = SPDR; // grab byte from SPI Data Register</p>
  if (pos < sizeof buf){ // add to buffer if room
    buf [pos++] = c;
    if (c == '*')  process_it = true;</p>
  } // end of room available</p>
} // end of interrupt routine SPI_STC_vect

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

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: