Issue when transferring string by SPI

Hi all,
I copy the code from http://www.gammon.com.au/forum/?id=10892
but don't know why the last letter is always send out as a first letter.

I try to send "hello world", but I have to send "ello, world!H", I don't have experience with C/C++ :sweat_smile:
what's wrong with the code.

Master

#include <SPI.h>

void setup (void) {
   Serial.begin(115200); //set baud rate to 115200 for usart
   digitalWrite(SS, HIGH); // disable Slave Select
   SPI.begin ();
   SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8
}

void loop (void) {
   char c;
   digitalWrite(SS, LOW); // enable Slave Select
   // send test string
   for (const char * p = "ello, world!H" ; c = *p; p++) 
   {
      SPI.transfer (c);
      Serial.print(c);
   }
   digitalWrite(SS, HIGH); // disable Slave Select
   delay(1);
}

Slave

#include <SPI.h>
char buff [50];
volatile byte indx;
volatile boolean process;

void setup (void) {
   Serial.begin (115200);
   pinMode(MISO, OUTPUT); // have to send on master in so it set as output
   SPCR |= _BV(SPE); // turn on SPI in slave mode
   indx = 0; // buffer empty
   process = false;
   SPI.attachInterrupt(); // turn on interrupt
}

ISR (SPI_STC_vect) // SPI interrupt routine 
{ 
   byte c = SPDR; // read byte from SPI Data Register
   if (indx < sizeof buff) {
      buff [indx++] = c; // save data in the next index in the array buff
      if (c == '\r') //check for the end of the word
      process = true;
   }
}

void loop (void) {
   if (process) {
      process = false; //reset the process
      Serial.println (buff); //print the array on serial monitor
      indx= 0; //reset button to zero
   }
}

You should declare the buffer as volatile as well as it's also being altered inside the SPI ISR.

1 Like

:face_with_thermometer: I don't know how to modify the code. :cold_sweat:

C strings end with a NULL char, zero. There is no carriage return in your string.

1 Like

You copied code you don't understand?

2 Likes

Do you now what the code you posted does? Can you understand it line by line?

In order to change the code, you first need to understand what it does, and how it does it.

1 Like

1. Look at the following diagram (Fig-1) to understand the data exchange mechanism between SPI-Master (UNO) and SPI-Slave(NANO).


Figure-1:

2. Upload the following sketches (Your sketches with slight simplification): (Hello World! appears on SM of Slave at 1-sec interval)
Master-UNO Sketch:

#include <SPI.h>
char myMsg[] = "Hello World!";

void setup ()
{
  Serial.begin(115200); //set baud rate to 115200 for usart
  SPI.begin ();
  digitalWrite(SS, HIGH); // disable Slave Select
  SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8
  //----------------------------
  digitalWrite(SS, LOW); // enable Slave Select
}

void loop ()
{
  for (byte i = 0; i < sizeof myMsg; i++)
  {
    SPI.transfer (myMsg[i]);
    delayMicroseconds(10);  //give time to Slave to process data
    Serial.print(myMsg[i]);
  }
  SPI.transfer('\r'); //CR as terminating charcater
  Serial.println();
  delay(1000);
}

Slave-NANO Sketch:

#include <SPI.h>
char buff [50];
volatile byte indx = 0;
volatile bool process = false;

void setup ()
{
  Serial.begin (115200);
  pinMode(MISO, OUTPUT); // have to send on master in so it set as output
  pinMode(SS, INPUT_PULLUP);
  SPCR |= _BV(SPE); // turn on SPI in slave mode
  SPI.attachInterrupt(); // turn on interrupt
}

void loop()
{
  if (process == true)
  {
    Serial.println (buff); //print the array on serial monitor
    process = false; //reset the process
    indx = 0; //reset button to zero
  }
}

ISR (SPI_STC_vect) // SPI interrupt routine
{
  byte ch = SPDR; // read byte from SPI Data Register
  buff [indx++] = ch; // save data in the next index in the array buff
  if (ch == '\r') //check for the end of the word
  {
    process = true;
    buff[indx] = '\0';  //insert null charcater
  }
}

3. OUTPUT:
Slave-NANO Serial Monitor shows:

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

4. Any question/query is welcomed!
5. Attached file may worth reading/experimenting.
Ch-8SPILec.pdf (357.5 KB)

1 Like

Hi GolamMostafa and all,
Thanks for the help! Especially for perfect document. I have to study more to understand the code.
This code seems put the \r in the front of the string if view as HEX, that seems to be issue same with what I have before.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.