top of page
Writer's pictureTasnemul Hasan Nehal

Sending "String" data - SPI

Objective:

We will send a String data (ex: "Hello") from Master to Slave Arduino


Theory:

Before we start coding we need to know the basics of how SPI communication works. I won't go with details here, you will better understand from joony786's article on SPI serial communication. It will be very helpful to understand the codes.


Hardware Setup:

Full Code:

Master Arduino

#include<SPI.h>             //main library


void setup() 
{
 Serial.begin(9600);       //MCU & Serial Monitor communication starts
 SPI.begin();              //SPI communication starts

 SPI.setClockDivider(SPI_CLOCK_DIV16);         //data transfering speed
 digitalWrite(SS, LOW);           //the clock pulse started from Master
}



void loop() 
{
  char a[]="Hello";                 //we will send this string to Slave
  
  for(int i=0; i<5; i++)            //"Hello" = 5 character
  {
   SPI.transfer(a[i]);              //sending byte by byte
  }
  delay(100);
}


Slave Arduino

#include<SPI.h>                               //main library

char c[10]="";                                //stores incoming string

int i=0;
volatile bool flag=false;


void setup() 
{
  Serial.begin(9600);
  SPI.setClockDivider(SPI_CLOCK_DIV16);

  pinMode(SS, INPUT_PULLUP);                  //make this device slave
  pinMode(MISO, OUTPUT);                      //transfer data to Master

  SPCR |= _BV(SPE);           
  SPCR |= !(_BV(MSTR));
  
  SPI.attachInterrupt();                      //data handler
}



void loop() 
{
  if(flag == true)                         //data received confirmation
  {
    Serial.println(c);
  }
  flag = false;                            //flag reset for next loop
                        
  delay(10);
}



ISR(SPI_STC_vect)
{
  c[i]= SPDR;                              //data received byte by byte
  i++;
  
  if(i == 5)                               //expected only 5 bytes
  {
   i=0;                                    //reset for next loop
   flag=true;                              //data received confirmation
  }                                                                     
}



Code Explanation:

At Master

SPI.begin();

SPI.begin() only used for Master, in slave we need to write multiple lines to establish the communication.

SPI.setClockDivider(SPI_CLOCK_DIV16);

Setting the data transferring speed at 1Mbit/s. Others option are "SPI.setClockDivider(SPI_CLOCK_DIVa)" where a=2,4,6,8,16,........

digitalWrite(SS, LOW);

The clock pulse started from Mastera, Slave cant start clock pulses. Without clock pulses, data can not be transferred.

SPI.transfer(a[i]);  

"SPI.transfer( )" can send only one byte at a time. Each character size is 1 byte. So without any conversion, we can directly send a character using this function.


At Slave:

volatile bool flag=false;

By using "volatile" we specified/fixed a memory location for "flag" which is a "bool" type variable, so next time when we need to access this variable compiler will know the exact location, the compiler won't need to reload and recheck variable's current/new memory location, unlike regular "int, float, char, bool" type variable. Learn more about it.

pinMode(MISO, OUTPUT); 

This line helps to transfer data from Slave to Master. Though we dont need to transfer data from Slave to Master here but I think it's a good practice to use a common pattern everywhere.

SPCR |= _BV(SPE);           
SPCR |= !(_BV(MSTR));

These 2 lines help to establish SPI communication from the Slave side, where at the master we only used "SPI.begin()"

SPI.attachInterrupt();      

When there will be any interference/data transfer, a default "ISR(SPI_STC_vect)" function will run automatically to eceive data. Here "SPI_STC_vect" is known as SPI status vector.

c[i]= SPDR;

"SPDR" is the register where data is saved byte by byte, but old data is replaced immediately after new data comes, that's why this function has to be as smallest as possible. No delay/print function can be used here. Because these functions may increase the run time and we can lose data. Here incoming byte from Master will be stored in the "c" variable


Result:

Slave's Serial Monitor




See More Examples:




Commentaires


Les commentaires ont été désactivés.
bottom of page