#include <SPI.h> // use the Arduino SPI library
#define SPI_MASTER_SLAVE_SEL_PIN (2) // SPI Master/Slave Select pin
#define SS_PIN (53) // 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 module
SPI.setDataMode(SPI_MODE0); // use SPI mode 0 (CPOL=0, CHPA=0)
SPI.setBitOrder(MSBFIRST); // use MSB first bit order
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 the pull-up on SS input pin
SPDR = 0xFF; // write 0xFF to SPDR
SPCR &= ~_BV(MSTR); // clear the MSTR bit (set to Slave mode)
SPCR &= ~_BV(CPOL); // clear the CPOL bit
SPCR &= ~_BV(CPHA); // clear the CPHA bit
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);
Serial.println();
digitalWrite(SS_PIN, LOW); // Activate SPI bus
recv_data = SPI.transfer(send_data); // Send & receive data
digitalWrite(SS_PIN, HIGH); // Deactivate SPI bus
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) {
SPDR = slave_recv_data; // Write received data to SPDR
slave_received = false; // Clear reception flag
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;
}