Tx and Rx 13 bytes over SPI

Hi!

I'm using two arduino uno boards for SPI communication, one acting as a master and other to be a slave. My aim is to transmit 100 bits (13 bytes, at same time instant) in binary format from master device to slave device, and receive back the same data at the master side, but unable to perform the same. I'm a beginner to arduino programming. The copy of the code tried is attached below.

Master code

#include<SPI.h> 
byte latch = 9;

byte mastersend[13] = {B11010011, B10110010, B10011101, B10101101, B10111001, B10110101, B10101101, B10110010, B10110010, B10110010, B10011101, B10011101, B10011101};
byte masterrecv[13];
 
void setup()
{
  Serial.begin(9600);
  pinMode(latch, OUTPUT);
  digitalWrite(latch, HIGH);
  digitalWrite(SS, HIGH);
  SPI.begin();
}

void loop()
{
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

  digitalWrite(SS, LOW);
  masterrecv = SPI.transfer(mastersend,13);
  Serial.println(mastersend, BIN);
  Serial.println(mastersend, BIN);
  SPI.endTransaction();
}

Here is the slave code which I tried for Tx and Rx 8 bits (1 byte). Kindly help me on writing 13 bytes from master to slave device and get back the same at master device.

Slave Code

#include <SPI.h>

volatile boolean datarecev;
volatile byte slaverecev;
volatile byte slavesend;

void setup (void)
{
  Serial.begin (9600);
    
  pinMode (MISO, OUTPUT);
  SPCR |= _BV(SPE);
  datarecev = false;
  
  SPI.attachInterrupt();
}

ISR (SPI_STC_vect)
{
  slaverecev = SPDR;
  datarecev = true;
}  

void loop (void)
{
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  
  if (datarecev)
    {  
      Serial.println(slaverecev, BIN);
  
      slavesend = slaverecev;
      SPDR = slavesend;
    }
}

Also, how do I print my data at both the Master and Slave side, in order to verify the data sent is received without any error.

Thanks.

You seem to enter a white spot on the Arduino map :frowning:

The only well known and supported part is the SPI master, almost nothing for proper slave coding. Seek for
SPI slave Arduino
to find out more.

Have you already tried the SPI.transmit(buf, size) method? As I understand it, it should transmit the data in buf[] and replace each byte by the received data. But most probably it will only work for the master, not for the slave.

Sending multiple bytes at once in master mode is easy, you add the required number of SPI.transmit() before SPI.endTransaction(). Use a for loop and index for outputting the bytes in your buffer array. Likewise the slave uses an index to store the received bytes in its input array. The slave index should be reset to zero when SS goes low (active), and MISO should be made an output at the same time. If you want to transmit the old data while receiving new bytes, also put the first buf[ 0] byte into the SPI data register. Then the slave ISR stores the incoming byte at the old index position buf[ i], increments the index and puts the buf[ i] into the outgoing register.

Of course the described procedure transmits the old data, not what's just being received.

https://forum.arduino.cc/index.php?topic=52111.0

@DrDiettrich

The slave code that is attached was used for receiving 1 byte, when the master device transmitted 1 byte data. But for the case of transmitting 13 bytes, I could code the master as attached above, but was unable to code the slave for the case of 13 bytes.

Learn using arrays; for your 13 bytes; array indexing and for loops. In the slave ISR you have to push each received byte into the next array element, as outlined before.

The "Hello world" example in reply #2 shows how to use an array and index for the received bytes.

Thanks for the guidance @ DrDiettrich
Working on the same.

Thanks for the reference @runaway_pancake

Is this the right way of using the array and index at the master side? Kindly help me where am going wrong in the code.

#include <SPI.h>
#include "pins_arduino.h"

byte masterSend[14] = {B11010011, B10110010, B10011101, B10101101, B10111001, B10110101, B10101101, B10110010, B10110010, B10110010, B10011101, B10011101, B10011101};
byte masterRecev[14];
byte i,j;

void setup(void)
{
  Serial.begin(9600); 
  digitalWrite(SS, HIGH);
  SPI.begin();
}

void loop(void)
{
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); 
  digitalWrite(SS, LOW);
  
  for(i=0; i<=14; i++)
  {
    for(j=0; j<=14; j++)
    {
      masterRecev[j] = SPI.transfer(masterSend[i]);
      Serial.print("Master Tx: ");
      Serial.println(masterSend[i], BIN);
      delay(2000);
      Serial.print("Master Rx: ");
      Serial.print(masterRecev[j], BIN);
      delay(2000);
      Serial.println();
    }
  }
 
  digitalWrite(SS, HIGH);
  delay(2000); 
  SPI.end();
}

Hello,

I am trying to communicate between Arduino UNO and an IC with 100 bit shift register over SPI with Arduino UNO as Master. I need to transfer (i.e, write into IC) 13 bytes data from arduino at a time. Here is the code written for arduino. Upon verifying with a signal oscilloscope, the data over MOSI pin did not match with the transmitted data. Can I know where am going wrong and How should I go about it?

Thanks!

#include <SPI.h>
#include "pins_arduino.h"

byte masterSend[13] = {B11010011, B10110010, B10011101, B10101101, B10111001, B10110101, B10101101, B10110010, B10110010, B10110010, B10011101, B10011101, B10011101};

void setup(void)
{
  Serial.begin(9600);
  digitalWrite(SS, HIGH);
  SPI.begin();
}

void loop(void)
{
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
  digitalWrite(SS, LOW);
 
  SPI.transfer(&masterSend, 13);
 
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

Also, how do I print my 100 bit data received from the IC at the master side? i.e, on the arduino serial monitor.

Try the following codes - your codes with slight codification:

#include <SPI.h>
#include "pins_arduino.h"

byte masterSend[13] = {
  B11010011, B10110010, B10011101, B10101101, B10111001, B10110101, B10101101, B10110010, 
  B10110010, B10110010, B10011101, B10011101, B10011101
};

void setup(void)
{
  Serial.begin(9600);
  digitalWrite(SS, HIGH);
  SPI.begin();
}

void loop(void)
{
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
  digitalWrite(SS, LOW);
 
  for(int i =0; i< 13; i++)
  {
     byte x = SPI.transfer(masterSend[i]);
     Serial.print(x, HEX);  //will print the received 13 bytes = 13x8 = 104 bits 
     Serial.print(' ');
     delay(1);
  }
 
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

@user_student

DO NOT CROSS POST.
TOPICS MERGED

It wastes peoples efforts to help you

please READ THIS before adding any more posts.

Bob.

Use a single for loop like this:

 for(int i =0; i< 13; i++)
     masterRecev[i] = SPI.transfer(masterSend[i]);

For 13 bytes the index is 0..12.
Show the results only after the transfer of all bytes is done, after SPI.endTransaction().

And you still can not read back the bytes just transmitted, because the slave will know the first value only after the first byte has been received.

DrDiettrich:
Use a single for loop like this:

 for(int i =0; i< 13; i++)

masterRecev[i] = SPI.transfer(masterSend[i]);



For 13 bytes the index is 0..12.
Show the results only after the transfer of all bytes is done, after SPI.endTransaction().

And you still can not read back the bytes just transmitted, because the slave will know the first value only **after** the first byte has been received.
  1. Your codes may not be working if you don't insert some delay between successive SPI.transfer() commands to cover the overhead activities to be taken by the slave to store data in the SPI Buffer.

  2. Data bytes being sent by the Master will not come back as the SPI buffer of the slave will be filled up by slave's own data.

GolamMostafa:
Try the following codes - your codes with slight codification:

  for(int i =0; i< 13; i++)

{
    byte x = SPI.transfer(masterSend[i]);
    Serial.print(x, HEX);  //will print the received 13 bytes = 13x8 = 104 bits
    Serial.print(' ');
    delay(1);
 }

}

Thanks for the guidance @GolamMostafa.

The above for loop prints/transfers the data repeatedly after the 13 bytes. How do I transfer/print them only once?

Because my IC needs to be loaded with 100 bit data only once at the same time instant.

user_student:
The above for loop prints/transfers the data repeatedly after the 13 bytes. How do I transfer/print them only once?

Execute the codes in the setup() function or insert while(1); code at the end of SPI.endTransaction(); line.

Thank you @GolamMostafa, that was really helpful.