#include <SPI.h> // use the Arduino SPI library
#define SPI_MASTER_SLAVE_SEL_PIN (2) // SPI Master/Slave Select pin
#define SS_PIN (10) // SPI Slave Select pin
boolean is_spi_master;
volatile boolean slave_received = false;
volatile uint8_t slave_recv_data = 0xff;
void setup() {
Serial.begin( 115200 );
pinMode( SPI_MASTER_SLAVE_SEL_PIN, INPUT_PULLUP );
if ( digitalRead(SPI_MASTER_SLAVE_SEL_PIN) == LOW ) {
is_spi_master = true;
} else {
is_spi_master = false;
}
if (is_spi_master) { // for SPI master/controller device
pinMode( SS_PIN, OUTPUT ); // use the SS pin for output
digitalWrite( SS_PIN, HIGH ); // output HIGH to the SS pin
SPI.begin(); // start the SPI master
SPI.setDataMode( SPI_MODE0 ); // use SPI mode 0 (CPOL=0,CHPA=0)
SPI.setBitOrder( MSBFIRST ); // use MSB-first bit order
// set clock divider for SCK
// use SPI_CLOCK_DIVx, where x=4,8,16,32,64,128
SPI.setClockDivider( SPI_CLOCK_DIV16 ); // 16MHz/16 = 1MHz
Serial.println( F("SPI Master...") );
delay( 100 );
}
else { // for SPI slave/peripheral device
pinMode( MISO, OUTPUT ); // configure the MISO pin as output
pinMode( SS_PIN, INPUT_PULLUP ); // enable internal pullup on SS input pin
SPDR = 0xFF; // write 0xFF to SPDR
// MSTR=0 (Slave mode), DORD=0 (MSB first), Mode 0 (CPOL=0, CPHA=0)
SPCR &= ~_BV(MSTR); // clear the MSTR bit (MSTR=0)
SPCR &= ~_BV(CPOL); // clear the CPOL bit (CPOL=0)
SPCR &= ~_BV(CPHA); // clear the CPHA bit (CPHA=0)
SPCR &= ~_BV(DORD); // clear the DORD bit (DORD=0)
SPCR |= _BV(SPE); // set the SPE bit to enable SPI
slave_received = false; // clear the slave data reception flag
SPI.attachInterrupt(); // enable the SPI interrupt
Serial.println( F("SPI Slave...") );
}
}
void loop() {
if ( is_spi_master ) { // SPI master operation
static uint8_t send_data = 0x00, recv_data;
Serial.print( F("Master> sent: 0x") );
Serial.print( send_data, HEX );
// pull the /SS pin LOW to activate the SPI bus
digitalWrite( SS_PIN, LOW );
// send-receive one data byte over the SPI bus
recv_data = SPI.transfer( send_data );
// pull the /SS pin HIGH to de-activate the SPI bus
digitalWrite( SS_PIN, HIGH );
Serial.print( F(", received: 0x") );
Serial.println( recv_data, HEX );
send_data += 1; // increment by 1
delay( 1000 );
}
else { // SPI slave operation
if ( slave_received ) {
// write the received data byte to SPDR
SPDR = slave_recv_data;
// clear the slave data reception flag
slave_received = false;
Serial.print( F("Slave: received 0x") );
Serial.println( slave_recv_data, HEX );
}
delay(1);
}
}
// ISR for 'SPI Serial Transfer Complete' (SPI Slave mode)
ISR(SPI_STC_vect) {
slave_recv_data = SPDR;
slave_received = true;
}