There is no particular reason why it shouldn't work, and indeed I got SPI and I2C to work together between two Unos.
Master:
// Written by Nick Gammon
// July 2011
// SPI/I2C master
#include <SPI.h>
#include <Wire.h>
#include "pins_arduino.h"
#define SLAVE_ADDRESS 42
// command we might send
#define CMD_ID 1
void setup (void)
{
Wire.begin();
Serial.begin(115200); // start serial for output
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
// Then put SPI hardware into Master mode and turn SPI on
SPI.begin ();
// Slow down the master a bit
SPI.setClockDivider(SPI_CLOCK_DIV16);
} // end of setup
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);
// disable Slave Select
digitalWrite(SS, HIGH);
delay (200); // 200 mS delay
Wire.beginTransmission (SLAVE_ADDRESS);
Wire.send (CMD_ID);
Wire.endTransmission ();
Wire.requestFrom (SLAVE_ADDRESS, 1);
if (Wire.available ())
{
Serial.print ("Slave is ID: ");
Serial.println (Wire.receive (), DEC);
}
delay (1000); // 1 second delay
} // end of loop
Slave:
// Written by Nick Gammon
// July 2011
// SPI/I2C slave
#include "pins_arduino.h"
#include <Wire.h>
char buf [100];
volatile byte pos;
volatile boolean process_it;
// command we might get
#define CMD_ID 1
#define MY_ADDRESS 42
char command;
void setup (void)
{
Serial.begin (115200); // 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);
Wire.begin (MY_ADDRESS);
Wire.onReceive (receiveEvent); // interrupt handler for incoming messages
Wire.onRequest (requestEvent); // interrupt handler for when data is wanted
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR; // grab byte from SPI Data Register
if (!process_it)
{
// 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
} // if not waiting for previous one to be processed
} // 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;
Serial.println (buf);
pos = 0;
process_it = false;
} // end of flag set
} // end of loop
void receiveEvent (int howMany)
{
command = Wire.receive (); // remember command for when we get request
} // end of receiveEvent
void requestEvent ()
{
switch (command)
{
case CMD_ID: Wire.send (0x55); break; // send our ID
} // end of switch
} // end of requestEvent
I connected together pins 10 .. 13 (for SPI) A4/A5 (for I2C) and +5V and Gnd.
Then uploaded both sketches and opened the serial monitor on each one.
One of them echoed back the "hello, world" that was being sent by SPI:
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
The other one echoes back the slave ID that was requested by I2C:
Slave is ID: 85
Slave is ID: 85
The slave uses interrupts to process both SPI and I2C incoming.