SPI Komunikation

Hello professionals,
I dont get any further. I use a mega as a master and a nano as a slave. I try to send text from master to slave, which works.
Now I want the slave to return another text.
But it does not matter to the master.
He shows me as a reception of what I send and not what has to come from the slave.
Master:

//Master
#include <SPI.h>
volatile boolean senden;
volatile char Paket_vom_Slave;
volatile char Paket_zum_Slave;
char buf [100];
volatile byte pos;
String Paket = "";
char x;

void setup (void)

{
  Serial.begin(9600);
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH);  //SS Pin auf HIGH setzten
  SPI.begin ();  //Verbindung starten
  SPI.setClockDivider(SPI_CLOCK_DIV8);  //Geschwindigkeit verlangsamen
}

void loop (void)
{

//Paket_vom_Slave="";
  digitalWrite(SS, LOW);    //starten der Kommunikation mit Slave

  for (const char * p = "TxT v Master\n" ; Paket_zum_Slave = *p; p++)
  {
    //Text_erstellen();
    Paket_vom_Slave = SPI.transfer(Paket_zum_Slave); //senden von Text
    Text_erstellen();
delayMicroseconds (500);
   
    Serial.print("sent: ");
    Serial.print(Paket_zum_Slave);
    Serial.print("\t empfangen: ");
    Serial.println(Paket_vom_Slave);
    delay(200);
  }
  digitalWrite(SS, HIGH);  //beenden der Kommunikation
  delay (1000);  //kurze pause

}

void Text_erstellen()
{

  char c = Paket_vom_Slave;  //kopieren der Daten von SPI Buffer
  if (pos < sizeof buf)
  {
    buf [pos++] = c;  //hinzufuegen des naechsten Zeichens
    if (c == '\n')
      senden = true;
  }
  if (senden)
  {
    buf[pos] = 0;
    Paket = (buf);
    x = buf;
    Paket.trim();
    Serial.println (("empfangen :--->") + (Paket));
    Serial.println (("empfangen :--->") + (Paket));
    Serial.println (("empfangen :--->") + (Paket));
    pos = 0;
    senden = false;

  }
}
  

//Slave
#include <SPI.h>
volatile boolean senden;
volatile boolean versandbereit;
//volatile byte Paket_Master,Sendung_Slave;
volatile char Paket_Master;
volatile char Sendung_Slave;
String Paket = "";
String Sendung = "";
int i = -1;
char buf [20];
char buf1 [20];
volatile byte pos;
volatile byte pos1;

void setup(void)
{
  Serial.begin(9600);
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);         // turn on SPI in slave mode

  //SPCR |= bit (SPE);
  senden = false;
  SPCR |= _BV(SPIE);   // turn on interrupts
  SPI.attachInterrupt();
}


void loop(void)
{

  if ((versandbereit) == false);
  {
    Paket_Text();
  }

  if (senden)
  {
    i = i + 1;

    buf[pos] = 0;
    Paket = (buf);
    buf1[pos] = 0;
    Sendung = (buf1);

    if (i == 12)
    {
      SPDR = "\n";
    }
    else
    {
      SPDR = (buf1[i]);
    }

    Paket.trim();
    Sendung.trim();
    Serial.println (("empfangen :--->") + (Paket));
    Serial.println (buf1[i]);
    Serial.println (i);
    Serial.println (("gesendet  :--->") + (Sendung));

    pos = 0;
    senden = false;
  }

  if (i == 12) i = -1;
}



ISR(SPI_STC_vect)
{

  byte c = SPDR;  //kopieren der Daten von SPI Buffer
  if (pos < sizeof buf)
  {
    buf [pos++] = c;  //hinzufuegen des naechsten Zeichens
    if (c == '\n')
      senden = true;
  }
}



void Paket_Text()
{
  if (pos1 < sizeof buf1)
    for (const char * p = "Paket--Slave\n" ; char c = *p; p++)
    {
      buf1 [pos1++] = c;
                            Serial.println (buf1);
      if (c == '\n')
        versandbereit = true;
    }
}

To make it easy for people to help you please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum

Normally SPI is a two-way process. While the master is sending a byte to the slave the slave is sending a byte to the master.

...R

This

    for (const char * p = "Mail  Server\n" ; c = *p; p++)
    {
      Sendung_Slave = c;
       //SPDR = 4;        //   (c);  //senden von Text
      SPDR = Sendung_Slave;
      Serial.print (c);
     //Serial.println (("gesendet :--->") + (c));
    }

doesn't work on the slave. The slave can only transmit one byte if the master is sending one byte at the same time. The clock signal for this transfer is provided by the master. So the master must know exactly how many bytes the slave wants to transfer. SPI is no replacement for a UART transfer where both sides are on the same level and each can send data if it wants to.
If you want to send a string from the slave to the master, the master first has to ask the slave for the length of the string and then send that amount of bytes to the slave (might be 0x00 bytes) to provide the clock signal for the reverse traffic.

Hello Thanks first for the hint.
I revised the slave and redone my first post.
With the change, it should now be ok with the slave.
But unfortunately, the master still gives me only the text he should send back.

//Slave
#include <SPI.h>
volatile boolean senden;
volatile boolean versandbereit;
//volatile byte Paket_Master,Sendung_Slave;
volatile char Paket_Master;
volatile char Sendung_Slave;
String Paket = "";
String Sendung = "";
int i = -1;
char buf [20];
char buf1 [20];
volatile byte pos;
volatile byte pos1;

void setup(void)
{
  Serial.begin(9600);
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);         // turn on SPI in slave mode

  //SPCR |= bit (SPE);
  senden = false;
  SPCR |= _BV(SPIE);   // turn on interrupts
  SPI.attachInterrupt();
}







void loop(void)
{

  if ((versandbereit) == false);
  {
    Paket_Text();
  }

  if (senden)
  {
    i = i + 1;

    buf[pos] = 0;
    Paket = (buf);
    buf1[pos] = 0;
    Sendung = (buf1);

    if (i == 12)
    {
      SPDR = "\n";
    }
    else
    {
      SPDR = (buf1[i]);
    }

    Paket.trim();
    Sendung.trim();
    Serial.println (("empfangen :--->") + (Paket));
    Serial.println (buf1[i]);
    Serial.println (i);
    Serial.println (("gesendet  :--->") + (Sendung));

    pos = 0;
    senden = false;
  }

  if (i == 12) i = -1;


}




ISR(SPI_STC_vect)
{

  byte c = SPDR;  //kopieren der Daten von SPI Buffer
  if (pos < sizeof buf)
  {
    buf [pos++] = c;  //hinzufuegen des naechsten Zeichens
    if (c == '\n')
      senden = true;
  }
}




void Paket_Text()
{
  if (pos1 < sizeof buf1)
    for (const char * p = "Paket--Slave\n" ; char c = *p; p++)
    {
      buf1 [pos1++] = c;
                            Serial.println (buf1);
      if (c == '\n')
        versandbereit = true;
    }
}

What is 'Komunikation' ?

I try to explain the mistake again, maybe someone has an idea for me.
I send to Master "TxT v Master \ n" at the character "\ n" the slave gives me the message correctly.
The slave sends back ____ "package - slave \ n", but the master only shows me the text he sends himself.
When I send something without a "\ n" character from the slave, the master does not put any text together
void text_create () no cancel. But since the slave sends the same character length, the transmission seems obvious.
When composing, however, the master only puts together what he sends. Do I have the worm somewhere?
Paket_vom_Sklave; is clearly the valid return and with "\ n" the slave comes with the demolition.
In case of an invalid return but not.
I hope my explanation is understandable Mfg Dieter

//Master
#include <SPI.h>
volatile boolean senden;
volatile char Paket_vom_Slave;
volatile char Paket_zum_Slave;
char buf [100];
volatile byte pos;
String Paket = "";


void setup (void)

{
  Serial.begin(9600);
//  pinMode(53, OUTPUT);
  pinMode(SS, OUTPUT);
 // digitalWrite(SS, HIGH);  //SS Pin auf HIGH setzten
  SPI.begin ();  //Verbindung starten
  SPI.setClockDivider(SPI_CLOCK_DIV8);  //Geschwindigkeit verlangsamen
}



void loop (void)
{
  //Text_erstellen();

  digitalWrite(SS, LOW);    //starten der Kommunikation mit Slave

  for (const char * p = "TxT v Master\n" ; Paket_zum_Slave = *p; p++)
  {
    //Text_erstellen();
    Paket_vom_Slave = SPI.transfer(Paket_zum_Slave); //senden von Text
    Text_erstellen();
    delayMicroseconds (500);

    Serial.print("sent: ");
    Serial.print(Paket_zum_Slave);
    Serial.print("\t empfangen: ");
    //Serial.println(Paket_vom_Slave);
    Serial.println(Paket);
    delay(200);
  }
  digitalWrite(SS, HIGH);  //beenden der Kommunikation
  delay (1000);  //kurze pause

}



void Text_erstellen()
{


  if (pos < sizeof buf)
  {
    char c = Paket_vom_Slave;  //kopieren der Daten von SPI Buffer
    buf [pos++] = c;  //hinzufuegen des naechsten Zeichens
    if (c == '\n')
      senden = true;
  }
  if (senden)
  {
    buf[pos] = 0;
    Paket = (buf);
    Paket.trim();
    Serial.println (("empfangen :--->") + (Paket));
    Serial.println (("empfangen :--->") + (Paket));
    Serial.println (("empfangen :--->") + (Paket));
    pos = 0;
    senden = false;
  }
}

If I have to change the pin mod how do I do that where I am still a stupid. Maybe someone can tell me where exactly I have to enter.

What is 'Komunikation' ?

That's communication in German but with a spelling error.

With the change, it should now be ok with the slave.

No. You still try to send at any time. The slave cannot actually send a byte to the master, it can only transfer exactly one byte back while the master is sending one byte. If the master doesn't send anything, the client cannot send anything to the master.

Yes, but the master always sends only one bit and at the same time it should always receive only one bit. The loop then sends the next bit exactly the same on the other side of the slave, he always returns only one bit.
I put together the slave then the string. On the master side should be composed also a string.
But it is not synonymous what is sent by the slave.

I'm getting on slowly :slight_smile:

But I currently have a problem with the data transfer.
I hand over at startup: char package_to_master [50] = "Start from the slave.";
and change SPI interrupt routine content with "new text"
but is sent "starting from the slave."
How should I change that?

// Slave
char Paket_zum_Master [50] = "Starten vom Slave.";
volatile int pos;
volatile bool active;
String Send_Paket;

ISR (SPI_STC_vect)    // SPI interrupt routine
{

Send_Paket = "neuer Text";
char Sendung = ((Send_Paket + "\n").c_str());
Paket_zum_Master [50] = Sendung;  

  
  byte c = SPDR;
  if (c == 1)  // starting new sequence?
    {
    active = true;
    pos = 0;
    SPDR = Paket_zum_Master [pos++];   // sendet erste byte
    return;
    }
  if (!active)
    {
    SPDR = 0;
    return;
    }
  SPDR = Paket_zum_Master [pos];
  if (Paket_zum_Master [pos] == 0 || ++pos >= sizeof (Paket_zum_Master)) //wenn pos =0 oder größer 1
    active = false;
}  // end of interrupt service routine (ISR) SPI_STC_vect

Yes, but the master always sends only one bit and at the same time it should always receive only one bit.

Now, the Arduino register holds a complete byte, so 8bits. It's correct that for every bit the master sends it gets one bit from the slave.

The loop then sends the next bit exactly the same on the other side of the slave, he always returns only one bit.
I put together the slave then the string. On the master side should be composed also a string.
But it is not synonymous what is sent by the slave.

I don't understand what you're trying to tell us. It might be better to ask the question again in the German part of the forum.

char Sendung = ((Send_Paket + "\n").c_str());
Paket_zum_Master [50] = Sendung;

This isn't doing what you described. This sets the byte after the last byte of the array "Paket_zum_Master" to the first byte of the address of the converted String "Send_Paket". So it writes to a memory region where you must not write because you don't know what there is.

Don't use the String class for Arduino code. It fragments the memory and sooner or later you run into memory problems.

Thank you for your answer pylon,
I declare a char at the beginning:
char packet_to_master [50] = "Starting from the slave.";
However, I would like to make this variably variable later at runtime

//This is not good:
char Sendung = ((Send_Paket + "\n").c_str());
Paket_zum_Master [50] = Sendung; 
//But unfortunately I do not have the success here either: 
Send_Paket = "neuer Text";
char Paket_zum_Master[100];
strcpy(Paket_zum_Master[100], Send_Paket.c_str());

//I am looking for a good solution
char packet_to_master [50] = variable (content Send_Paket)

However, I would like to make this variably variable later at runtime

I have no clue what this sentence means.

char Sendung = ((Send_Paket + "\n").c_str());
Paket_zum_Master [50] = Sendung;

String.c_str() returns a C string which is a character array and not a character.
Paket_zum_Master is defined as a character array of size 50. So accessing Paket_zum_Master[50] is already a buffer overflow, you're accessing memory you're not allowed to.

strcpy(Paket_zum_Master[100], Send_Paket.c_str());

strcpy expects two parameters, both being C strings or character arrays. Pakete_zum_Master[100] is one character but again a buffer overflow.

You shouldn't mix the String class and C style strings, especially if you're not experienced working with both of them. On the Arduino platform you should not use the String class at all as it fragments your memory much too fast and sooner than you might think you run into memory problems which often show up as very strange symptoms. Stick with C strings (character arrays) and learn how to use them properly.

In your special case you should seriously rethink your decision to use SPI for transferring strings. Although this is possible, it makes sense only in very, very seldom cases.