SPI Arduino Master to Arduino Slave

Folks,

I am working on emulating an SPI slave with a second arduino to ease the process of troubleshooting accessing multiple SPI devices on the same bus.

I have successfully setup several simple examples transferring data from one Ardunio serving as a Master to second one serving as a Slave and from the Slave to the Master. Where I am having problems is implementing a more sophisticated interface where the Master sends commands to the Slave and the Slave responds with Results.

My hardware setup has the following pin mappings:

Master Slave
A1 D2 to A2 D5
A1 D10 to A2 D10
A1 D11 to A2 D11
A1 D12 to A2 D12
A1 D13 to A2 D13

Both Ardunio A1 and Ardunio A2 share a common ground.

The goal is:

  1. When the Slave has data to send the Master it initiates interrupt 0 via pin 5/pin 2.
  2. The Master sends a byte with the value of 17 to the Slave letting it know it is ready to read data.
  3. The Slave on getting 17 sends the Mater a byte of value 19. Eventually this will be more sophisticated data.

The problem is that the Slave hangs after sending 19 to the Master. It looks like this is Slave is not seeing the SPIF bit set when the bit shift completes. I have read the documentation for SPI on the ATmega328 and it looks to me like the SPIF bit should be getting set.

I have come up with several work arounds but I would like to see if there is a way to make it work as it would appear the documentation says it should.

Any help would be much appreciated.

Thanks,

digitalhack

Master Code

// Master

#define SCK_PIN   13
#define MISO_PIN  12
#define MOSI_PIN  11
#define SS_PIN    10

void MasterInit(void) {  
  // initialize the SPI pins
  pinMode(SCK_PIN, OUTPUT);
  pinMode(MOSI_PIN, OUTPUT);
  pinMode(MISO_PIN, INPUT);
  pinMode(SS_PIN, OUTPUT);

  // Enable SPI, set as Master
  SPCR = B00000000;
  SPCR = (1<<SPE)|(1<<MSTR);
}

byte ReadByte(void) {
  while(!(SPSR & (1<<SPIF))) ;
  return SPDR;
}

void WriteByte(byte value) {
  SPDR = value;
  while (!(SPSR & (1<<SPIF))) ;
  return;
}

volatile boolean SlaveDataFlag = false;

void isr(void) {
  SlaveDataFlag = true;
}

void setup() {
  Serial.begin(57600);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  attachInterrupt(0, isr, LOW);
  MasterInit();
  digitalWrite(SS_PIN, HIGH);
}

void loop() {
  byte txData;
  byte rxData;
  while (true) {
    if (SlaveDataFlag) {
      Serial.println("Slave has data...");

      Serial.println("Writing data to slave...");

      digitalWrite(SS_PIN, LOW);
      WriteByte(17);
      Serial.println("Done Writing data...");

      Serial.println("Reading data from slave...");
      rxData = ReadByte();
      digitalWrite(SS_PIN, HIGH);

      Serial.println("Done Reading data...");

      Serial.print("From Slave: ");
      Serial.println(rxData, DEC);
      SlaveDataFlag = false;
    }
  }
}

Slave Code

// Slave

#define SCK_PIN   13
#define MISO_PIN  12
#define MOSI_PIN  11
#define SS_PIN    10

void SlaveInit(void) {
  // Set MISO output, all others input
  pinMode(SCK_PIN, INPUT);
  pinMode(MOSI_PIN, INPUT);
  pinMode(MISO_PIN, OUTPUT);
  pinMode(SS_PIN, INPUT);

  // Enable SPI
  SPCR = B00000000;
  SPCR = (1<<SPE);
}

byte ReadByte(void) {
  while(!(SPSR & (1<<SPIF))) ;
  return SPDR;
}

void WriteByte(byte value) {
  SPDR = value;
  while (!(SPSR & (1<<SPIF))) ;
  return;
}

unsigned long lastSent;

void setup() {
  Serial.begin(57600);
  digitalWrite(5, HIGH);
  SlaveInit();
  lastSent = millis();
  pinMode(5, OUTPUT);
}

void loop() {
  if (digitalRead(10) == LOW) {
    Serial.println("Pin 10 low...");
    byte rxData;
    rxData = ReadByte();
    Serial.print("Command: ");
    Serial.println(rxData, DEC);
    if (rxData == 17) {
      Serial.println("Sending data to master...");
      WriteByte(19);
      Serial.println("Done Sending data...");
    }
  }
  if (millis() > lastSent + 2000) {
    Serial.println("Pin 5 low...");
    digitalWrite(5, LOW);
    delay(10);
    digitalWrite(5, HIGH);
    lastSent = millis();
  }
}

Output from Master

Slave has data...
Writing data to slave...
Done Writing data...
Reading data from slave...
Done Reading data...
From Slave: 19

Output from Slave

Pin 5 low...
Pin 10 low...
Command: 17
Sending data to master...