SPI Communication with Interrupt in Arduino

SPI Communication with Interrupt in Arduino

Hello everyone, in this article we are going to talk about SPI Communication with Arduino. We will talk about the spi usage first and then we will make an example on communication between two arduinos with SPI.

Let's get started.

First What is SPI?

SPI stands for Serial Periphal Interface. SPI lets the devices to communicate with each other to share information. In most application environmental devices use the SPI communication protocol to send the sensor value to device. SPI communication has one master device. This master device manage the everything.

SPI has 3 lines. These are: MOSI, MISO and SCK. Sometimes we may need to communicate with multiple devices. In that case we will need external lines to set the active device. These lines call as CS (Chip Selection) or SS (Slave Selection). When we set the related devices SS pin as 0Volt we selected this related device. Below you will see the meanings of these lines:

  • MOSI: Stands for Master Output Slave Input. This line lets the master device to send datas to the Slave device.
  • MISO: Stands for Master Input Slave Output. This line lets the master device to receive datas from slave devices.
  • SCK: This line oscilates the clock signal from the master device. This signal will synchronise the communication to make communication healthy.

Below image you can see the SPI Communication Schematic:

SPI Communication Schematic

Now let's make an example with Arduino. In this example we are going to let the two arduinos to communicate with each other.

Below image you can see the pin connections of these two arduinos.

Arduino SPI Communication Schmatic

We selected the 11, 12 and13 as communication pins, and we set the 10. pin as Slave Selection pin. Also if you want to supply energy them seperatelly or you can connect them with 5V pins to supply both of them from connected arduino with USB to read serial datas.

Before The examples I want you to read the SPI hardware structs of the arduino.

SPCR Bit Values


| 7    | 6    | 5    | 4    | 3    | 2    | 1    | 0    |
| SPIE | SPE  | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 |

SPIE - Enables the SPI interrupt when 1
SPE - Enables the SPI when 1
DORD - Sends data least Significant Bit First when 1, most Significant Bit first when 0
MSTR - Sets the Arduino in master mode when 1, slave mode when 0
CPOL - Sets the data clock to be idle when high if set to 1, idle when low if set to 0
CPHA - Samples data on the falling edge of the data clock when 1, rising edge when 0
SPR1 and SPR0 - Sets the SPI speed, 00 is fastest (4MHz) 11 is slowest (250KHz)

First I will write the Master Device code.

MasterDevice.ino


//SPI Master Device
//We need to import SPI.h library first 
#include <SPI.h>
//Our Slave Selection pin
#define SlaveSelection  10

int count = 0;

void setup()
{
  //Set SlaveSelection pin as output.
  pinMode(SlaveSelection, OUTPUT);
  //and Make it HIGH to prevent to start communication right away
  digitalWrite(SlaveSelection, HIGH);
  //Start the SPI communication.
  SPI.begin();
}
 
void loop()
{

    for(count=0; count<255; count++){
      sendSerialData(count , SlaveSelection);
      delay(2000);
    }
    delay(500);
}
 
void sendSerialData(char data, int SlaveSelection)
{
  //Enable slave arduino with setting the SlaveSelection pin to 0Volt
  digitalWrite(SlaveSelection, LOW);
  // Wait for a moment 
  delay(10);
  //We sent the data here and wait for the response from device
  char receivedValue = SPI.transfer(data);
  //And then write the answer to the serial port
  Serial.println(receivedValue);
  //Disable slave arduino with setting the SlaveSelection pin to 5Volt
  digitalWrite(SlaveSelection, HIGH);
}

Below code block you will see the Slave Device Code:

SlaveDevice.ino


//Slave device of the SPI communication
#include <SPI.h>

char i = 0;

#define SlaveSelection  10

void setup()
{
  //Start the Serial Communication
  Serial.begin(9600);   
    
  // initialize SPI :
  pinMode(SlaveSelection , INPUT); // Set SlaveSelection as input
  pinMode(13,OUTPUT);   // Set clk as output
  pinMode(11,OUTPUT);   // Set MOSI as output
  pinMode(12,INPUT);    // Set MISO as input
  
  // SPCR - SPI Control Register
  // According to struct table we enable the SPI and Interface
  SPCR  |= 0b11000000;
  // SPSR - SPI Status Register
  SPSR  |= 0x00;
}  
 
void loop()
{
  delay(1000);
}

//SPI Interrupt function 
ISR(SPI_STC_vect)
{
    //Here we read the SPI lines
    //This line will check data for every ASCII codes for 8-bit received data
    //SPDR -> SPI Data Read bit
    SPDR = i;
    i ++;
    if ( i > 255) 
      i = 0;
    while(!(SPSR & (1 << SPIF)));
    //Load the received data to the variable
    char received = SPDR;
    //And send it to the serial communication bus
    Serial.println(received);
}

Now we are ready for the communication between two arduinos with the arduino.

You can reach the example application on github link https://github.com/thecodeprogram/Arduino_SPI_Example

That is all in this article.

Have a good SPI communication.

Burak Hamdi TUFAN


Tags


Share this Post

Send with Whatsapp

Post a Comment

Success! Your comment sent to post. It will be showed after confirmation.
Error! There was an error sending your comment. Check your inputs!

Comments

  • Thecodeprogram User
    Richard Tam

    Thanks for the SPI example code. What I am confused with slave side: pinMode(13,OUTPUT); // Set clk as output pinMode(11,OUTPUT); // Set MOSI as output pinMode(12,INPUT); // Set MISO as input Should the SCK, MOSI defined as input for slave side?

    2021/07/13 05:01:10
    • Thecodeprogram User
      Burak Hamdi TUFAN

      In this article we just let the master to send data to slave over SPI. To perform this we made master arduinos Master Output pin as output; input pin of slave arduino as input. MOSI is not important for slave arduino and MISO is not important for master arduino.

      If you need to use them you can activate these pins.

      2021/07/13 17:51:17