First of all, let's do the hardware connection.
#include <SPI.h>
#define SS_PIN 10 // Slave Select pin for SPI
#define SWITCH_PIN 2 // Push button pin
// Variables for button handling
bool ledState = false; // Tracks the LED state (ON/OFF)
const uint8_t DEBOUNCE_DELAY = 50; // Debounce delay in milliseconds
// Button state variables
unsigned long lastDebounceTime = 0; // Last recorded debounce time
uint8_t lastButtonState = HIGH; // Last stable state of the button
uint8_t buttonState = HIGH; // Current state of the button
void setup() {
pinMode(SS_PIN, OUTPUT); // Set Slave Select (SS) pin as output
pinMode(SWITCH_PIN, INPUT_PULLUP); // Set push button pin as input with pull-up resistor
// Initialize SPI communication
SPI.begin(); // Start SPI
digitalWrite(SS_PIN, HIGH); // Ensure SS is HIGH (deselect the slave)
}
void loop() {
// Check if the button is pressed
if (isButtonPressed()) {
// Toggle the LED state
ledState = !ledState;
// Begin SPI communication with the slave
digitalWrite(SS_PIN, LOW); // Pull SS low to select the slave
if (ledState) {
SPI.transfer(0x01); // Send ON command (0x01) to the slave
} else {
SPI.transfer(0x00); // Send OFF command (0x00) to the slave
}
digitalWrite(SS_PIN, HIGH); // Deselect the slave by setting SS high
}
}
/**
* Checks if the button is pressed with debouncing.
*
* @return true if a valid button press is detected, false otherwise.
*/
bool isButtonPressed() {
int reading = digitalRead(SWITCH_PIN);
// If the button state has changed since the last read
if (reading != lastButtonState) {
lastDebounceTime = millis(); // Update debounce timer
}
lastButtonState = reading;
// If the button state remains stable for the debounce delay period
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
// If the button state has changed
if (reading != buttonState) {
buttonState = reading;
// Return true if the button is pressed (LOW state)
if (buttonState == LOW) {
return true;
}
}
}
// Return false if no valid press is detected
return false;
}
#include <SPI.h>
#define LED_PIN 3 // LED connected to Pin 3
volatile byte receivedData = 0; // Variable to store received data from SPI
bool flag = 0; // Flag to indicate data received
void setup() {
pinMode(LED_PIN, OUTPUT); // Set LED pin as output
digitalWrite(LED_PIN, LOW); // Ensure LED is OFF initially
// Configure SPI in slave mode
pinMode(MISO, OUTPUT); // Set MISO (Master In Slave Out) as output
SPCR |= _BV(SPE); // Enable SPI in slave mode
// Attach SPI interrupt for data reception
SPI.attachInterrupt(); // Enable SPI interrupt
}
/**
* Interrupt Service Routine (ISR) for SPI communication
* This gets triggered whenever data is received via SPI.
*/
ISR(SPI_STC_vect) {
receivedData = SPDR; // Read received data from SPI Data Register
flag = 1; // Set flag to indicate data received
}
void loop() {
// Check if data has been received
if (flag) {
// Control LED based on received data
if (receivedData == 0x01) {
digitalWrite(LED_PIN, HIGH); // Turn ON LED if data is 0x01
} else if (receivedData == 0x00) {
digitalWrite(LED_PIN, LOW); // Turn OFF LED if data is 0x00
}
flag = 0; // Reset flag after processing the data
}
}
1. Setup:
2. Interrupt Routine:
3. Main Loop:
We can see in the video, that as we click the button on the master the LED connected to the slave is toggling.