How to read multiple SPI responses?

Hello everyone,

I use my ESP32 as an SPI slave.

Another system, master, sends the following messages to the ESP32:

As you can see, the SPI master sends 2 message.
The first does not interest me. I would like to read only the 2nd and the following ones if they exist

Currently with my code I only display some 0.

#include <ESP32SPISlave.h>

ESP32SPISlave slave;

static constexpr uint32_t BUFFER_SIZE {5};
uint8_t spi_slave_tx_buf[BUFFER_SIZE];
uint8_t spi_slave_rx_buf[BUFFER_SIZE];

void setup() {
    Serial.begin(115200);
    delay(2000);

    // begin() after setting
    // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12
    // VSPI = CS: 5, CLK: 18, MOSI: 23, MISO: 19
    slave.setDataMode(SPI_MODE3);
    slave.setQueueSize(1);  // transaction queue size
    slave.begin();          // default SPI is HSPI
    // slave.begin(VSPI);   // you can use VSPI like this

    // clear buffers
    memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
    memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
}

void loop() {
    
   if (slave.remained() == 0)
   slave.queue(spi_slave_rx_buf, spi_slave_tx_buf, 5);

    // if transaction has completed from master,
    // available() returns size of results of transaction,
    // and buffer is automatically updated

    while (slave.available()) {
        // show received data
        for (size_t i = 0; i < 5; ++i) {
            Serial.printf(" %02x\r", spi_slave_tx_buf[i]);
        }
        printf("\n");

        slave.pop();
    }
    delay(5000);
}

How to correctly display the received messages after the first one please?

no one can help?

Count the number of times the ESP32's SPI CS pin goes low. Ignore the first go low and process the other go-lows. After a small time reset the csGoLowCount.

Also putting the ESP32 to sleep for 5 seconds does not make sense when trying to receive a string of SPI packets.

thanks a lot for your help!

Could you tell me more how to do that with my current code ?

Just have the Master drop the CS line to the slave and count the number of times the CS line drops.

Which pin on the slave are you using for the CS line?

Or are you just receiving all the SPI traffic without a CS line to use to discriminate traffic to a device?

I think your problem might be:

That is going to sit for 5 seconds after reading the first messages and before adding a new slave to the input queue. I suspect the second message comes in during those 5 seconds and is ignored because no receive buffer is available for it.

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_slave.html

1 Like

Thanks a lot for your help

Just have the Master drop the CS line to the slave and count the number of times the CS line drops.

Which pin on the slave are you using for the CS line?

Or are you just receiving all the SPI traffic without a CS line to use to discriminate traffic to a device?

Not sure to anderstand "just have the master drop the CS line..."
I can't control the master, is a "blackbox"

I use the pin 15 for the CS (blue signal in my picture)

How I can count a drop ?

That is going to sit for 5 seconds after reading the first messages and before adding a new slave to the input queue. I suspect the second message comes in during those 5 seconds and is ignored because no receive buffer is available for it.

I already try to delete the delay or have a longer, same result

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_slave.html

Thanks for this. The problem is I use arduino with the ESP32. I'm a noob in this field, I don't know how to use esp-idf. I'm afraid it be more diffuclt for me to use it.

I found someone who has the same problem here and resolve it by force the CS line and to low?

Unfortunately, I don't understand how to do with arduino lib...

What would you like me to do about this?

I was able to move forward thanks to your remarks which inspired me.

What I have done :
Instead of using the CS of the master, I use an ESP32 pin configured in OUTPUT and connected to the CS_slave. This way I can decide to switch this pin to LOW only after having received the 1st frame. So I know how to read the message from the 2nd frame.

The problem is that, in this way, I can read only the 2nd frame but not the following ones.
I'm still stuck...

How to read all frames every time CSB signal goes 0...

Edit your code so it no longer does that.

1 Like

Edit your code so it no longer does that.

But how :smile: ?

Here my whole code, if someone can found the probleme:

#include <ESP32SPISlave.h>

ESP32SPISlave slave;
static constexpr uint8_t VSPI_SS {SS};
SPIClass master(VSPI);

static constexpr uint32_t BUFFER_SIZE {5};
static constexpr uint32_t BUFFER_SIZE2 {5};

uint8_t spi_slave_tx_buf[BUFFER_SIZE2];
uint8_t spi_slave_rx_buf[BUFFER_SIZE2];
uint8_t spi_master_tx_buf[BUFFER_SIZE];
uint8_t spi_master_rx_buf[BUFFER_SIZE];



void set_buffer() {
    
  spi_master_tx_buf[0]=0x00;
  spi_master_tx_buf[1]=0x06;
  spi_master_tx_buf[2]=0x3B;
  spi_master_tx_buf[3]=0x11;
  spi_master_tx_buf[4]=0xE9;
}



void setup() {
    Serial.begin(115200);
    delay(2000);

   // begin() after setting
    // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12
    // VSPI = CS: 5, CLK: 18, MOSI: 23, MISO: 19
    slave.setDataMode(SPI_MODE3);
    slave.setQueueSize(1);  // transaction queue size
    slave.begin();          // default SPI is HSPI
    
    // clear buffers
    memset(spi_slave_tx_buf, 0, BUFFER_SIZE2);
    memset(spi_slave_rx_buf, 0, BUFFER_SIZE2);

    // SPI Master
    // VSPI = CS: 5, CLK: 18, MOSI: 23, MISO: 19
    pinMode(VSPI_SS, OUTPUT);
    digitalWrite(VSPI_SS, HIGH);
    master.begin();
    set_buffer();

}

void mastercmd(){
    // start master transaction
    master.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE1));
    digitalWrite(VSPI_SS, LOW);
    delayMicroseconds(1);
    master.transferBytes(spi_master_tx_buf, spi_master_rx_buf, BUFFER_SIZE);
    delayMicroseconds(2);
    digitalWrite(VSPI_SS, HIGH);
    master.endTransaction();   
}

void loop() {
    
  if (slave.remained() == 0)
   slave.queue(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE2);
    
   mastercmd();  //sending the frame

   while (slave.available()) {
        // show received data
        for (size_t i = 0; i < BUFFER_SIZE2; ++i) { 
            Serial.printf(" %02x\r", spi_slave_rx_buf[i]);   
        }
        printf("\n");

        //slave.pop();
    }    
}

To summarize

  1. With ESP32 VSPI (master) I send a trame to the slave pins of an external device
  2. The master pins of this device send back several frame to the ESP32 HSPI (slave)
  3. I would like to read all these frame received.

With this current code, I can only read the 1st frame. I understabd that each time the CSB signal switch low to high, the reading is over. So it can't read next frame.

I'm sure is not so difficult to do, but I don't have enough knowledge ...

What do you think ?

You may struggle to do this. How do you know which is the "first" message/byte? If the master is already sending when your ESP32 boots, then you have missed the first message/byte and potentially many others.

Is there a detectable gap between groups if messages so that you can use that to re-sync with the master. Or have I misunderstood the question.

Finally, it's ok if I read all frames, include the 1st one.
So as I explain in my previous message, with the code I showed, I only display the 1st message. Now I need help to display every following messages (see the picture).

It should be possible, right?

Hi everyone,
still need help to read several SPI rame, there is someone motivated to help me please :grin:

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