Go Down

Topic: SPI transfer data 1040 bytes (Read 562 times) previous topic - next topic

architap

Hello,

I am trying to communicate between Arduino DUE and STM32F over SPI with Arduino Due as Master. I need to transfer data of 1040 bytes.

How should I go about it?

Thanks!

weird_dave

Set up the STM32 SPI to be a slave, use SPI.transfer(buffer, size) to do the transfer at the Due end. Make sure both are set to use the same SPI mode.
I'm using this method to communicate with a FPGA, Due as master, full duplex transfer of 744 bytes at regular intervals.
This code will work, you just need to put something useful in the buffer (TxBuf) and perhaps read anything from it that comes back. You may wish to try it with a lower SPI clock to start with though.

Code: [Select]
#include <SPI.h>

const int TxBuf_Size = 1040;
const unsigned long looptime = 2000; //2ms
const int SPI_CS_pin = 4;

byte TxBuf[TxBuf_Size];
unsigned long current_micros;

void setup()
{
  //put some setup stuff in here
}

void loop()
{
  current_micros = micros();
  SPI.beginTransaction(SPISettings(28000000, MSBFIRST, SPI_MODE0));
  digitalWrite(SPI_CS_pin, LOW);
  SPI.transfer (&TxBuf, TxBuf_Size);
  digitalWrite(SPI_CS_pin, HIGH);
  SPI.endTransaction();
  //Note that TxBuf now contains recieved data

  //wait for the looptime befor carrying on
  while ((micros()- current_micros)<looptime);
}

maria_spi

Thank you! This was really helpful. I also have another question to add to the one asked here. How can I see what value is being returned from STM32 to Due? Can I do that just by using serial.println?


weird_dave

You can do that yes, I'd use a combination of Print and Println to make a table of all the values
Here's a snip from my code which does that, it prints a row of 32 bytes in Hex with leading zero's so that all the rows are the same length. It also puts a blank line every 10 lines printed (that's the "if(upCounter % 320 == 319)" bit of the code)
It also puts a bunch of spaces after every 8 bytes, just to make it easier to find your way around the data: (you'll need to change the buffer name as this really is a copy/paste from my code)

Code: [Select]
Serial.println("FPGA Data");
      for (upCounter = 0; upCounter < dataLen; upCounter++)
      {
        if (fpgaStatusMsg.rawData[upCounter] < 16)
        {
          Serial.print("0");
        }
        Serial.print(fpgaStatusMsg.rawData[upCounter], HEX);
        Serial.print(" ");
        if (upCounter % 32 == 31)
        {
          Serial.println("");
        }
        else if (upCounter % 8 == 7)
        {
          Serial.print("    ");
        }
        if(upCounter % 320 == 319)
        {
          Serial.println("");
        }
      }



maria_spi

Hello weird_dave,

Thank you so much for the code snippet. So in the earlier comment of yours, can you explain to me the time loop in the last line? Also I am trying to check the value of the first byte of 1040 bytes message that I send. Could you tell me how I can do that?

Thanks!!

weird_dave

The last line of the loop relies on the first line of the loop;

Code: [Select]
//first line
current_micros = micros();

//last line
while ((micros()- current_micros)<looptime);


the while statement keeps running until the 'looptime' number of microseconds has passed. This isn't the best way to do it to be honest, but it mostly works.
The first line grabs the current time (sort of, it's just a microsecond counter) so we can see how much time has passed.

The second code snippet, once adjusted to match your code, should print all 1040 bytes to the serial monitor. You'll want to slow the repetition rate down for testing purposes.
If you really only want to print the first byte, just use:
Code: [Select]
Serial.println(MyBuffer[0]);

where MyBuffer is the buffer filled from the SPI.transfer(), in my SPI snippet that was TxBuf

Go Up