Send 32 bit SPI request and receive 32 bit response

I am trying to communicate with acceleration sensor via SPI bus. Data word length is 32 bit, the data is transfered MSB first, SPI mode is 0 (zero). Below the function I use to send and receive the data. Unfortunately it does not work. I do not what I am doing wrong, I receive only zeros.

I have also tried with SPI.transfer(buffer, size), unfortunately did not work either.

uint32_t SendRequest(uint32_t Request)
{
    uint32_t Response;
    digitalWrite(PIN_CSB, LOW);

    // Split Request into 8-bit sections and sending them one byte at a time
    uint8_t byteOne = Request >> 24;
    SPI.transfer(byteOne);
    
    uint8_t byteTwo = Request >> 16;
    SPI.transfer(byteTwo);
    
    uint8_t byteThree = Request >> 8;
    SPI.transfer(byteThree);
    
    uint8_t byteFour = Request & 0xFF;
    Response = SPI.transfer(byteFour);
    
    digitalWrite(PIN_CSB, HIGH);
    return (Response);
}

So, I can not use UNO, as it's buffer is 16 bit. Now I am trying with ESP32. So far not successful, but let's see.

No one knows? :o

Your original approach would be fine- just split the incoming data into 4 bytes. With 40 posts on the forum you should know that no one is going to be able to help you unless you give us more details about your hardware setup.

Sorry for being not specific. I thought it is not necessary.

I want to communicate with Murata gyroscopic/acceleration sensor via SPI.
Datasheet of the sensor: https://www.murata.com/~/media/webrenewal/products/sensor/pdf/datasheet/datasheet_scc2230-e02.ashx?la=en-us

#include "SPI.h"

#define PIN_MOSI 23
#define PIN_MISO 19
#define PIN_CSB 5
#define PIN_SCK 18
#define PIN_EXTRESN 15 // external reset

// Standard requests
#define REQ_READ_RATE 0x040000f7
#define REQ_READ_ACC_X 0x100000e9
#define REQ_READ_ACC_Y 0x140000ef
#define REQ_READ_ACC_Z 0x180000e5
#define REQ_READ_TEMP 0x1c0000e3
#define REQ_WRITE_FLT_60 0xfc200006
#define REQ_WRITE_FLT_10 0xfc1000c7
#define REQ_READ_STAT_SUM 0x7c0000b3
#define REQ_READ_RATE_STAT1 0x240000c7
#define REQ_READ_RATE_STAT2 0x280000cd
#define REQ_READ_ACC_STAT 0x3c0000d3
#define REQ_READ_COM_STAT1 0x6c0000ab

uint32_t Response_Rate;
uint32_t Response_Acc_X;
uint32_t Response_Acc_Y;
uint32_t Response_Acc_Z;
uint32_t Response_Temp;
uint8_t RSdata; // Return Status - page 26

// Frame field masks
#define RS_FIELD_MASK 0x03000000

uint32_t SendRequest(uint32_t Request)
{
    uint32_t Response;
    digitalWrite(PIN_CSB, LOW);

    // Split Request into 8-bit sections and sending them one byte at a time
    Response = SPI.transfer(Request >> 24);
    Response = Response << 8;
    Response = SPI.transfer(Request >> 16);
    Response = Response << 8;
    Response = SPI.transfer(Request >> 8);
    Response = Response << 8;
    Response = SPI.transfer(Request);
    digitalWrite(PIN_CSB, HIGH);
    return (Response);
}

void setup()
{
    char Buffer[80];
    uint32_t Response_StatSum;
    uint32_t Response_RateStat1;
    uint32_t Response_RateStat2;
    uint32_t Response_AccStat;
    uint32_t Response_ComStat1;
    bool StartupOK;

    Serial.begin(115200);
    delay(10);
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
    SPI.setClockDivider(SPI_CLOCK_DIV16);
    Serial.println("Initializing...");
    delay(1000);

    pinMode(PIN_MOSI, INPUT);
    pinMode(PIN_MISO, OUTPUT);
    pinMode(PIN_CSB, OUTPUT);
    pinMode(PIN_SCK, OUTPUT);
    pinMode(PIN_EXTRESN, OUTPUT);

    SendRequest(0xfc200006);
    delay(600);
    SendRequest(REQ_READ_RATE_STAT1);
    SendRequest(REQ_READ_RATE_STAT2);
    SendRequest(REQ_READ_ACC_STAT);
    SendRequest(REQ_READ_COM_STAT1);
    SendRequest(REQ_READ_STAT_SUM);
    delay(1000);

    Response_StatSum = SendRequest(REQ_READ_STAT_SUM); // Read Status Summary register again to get
    RSdata = (Response_StatSum & RS_FIELD_MASK) >> 24; // the correct return status (RS) data from off-frame
    if (RSdata != 1) StartupOK = false;
    if (!StartupOK)
    {
        Serial.println("\r\nStart-up RS error\r\n");
        sprintf(Buffer, "Status Summary = 0x%X\r\n", Response_StatSum);
        Serial.println(Buffer);
        SendRequest(REQ_READ_RATE_STAT1);

        Response_RateStat1 = SendRequest(REQ_READ_RATE_STAT2);
        Response_RateStat2 = SendRequest(REQ_READ_ACC_STAT);
        Response_AccStat = SendRequest(REQ_READ_COM_STAT1);
        Response_ComStat1 = SendRequest(REQ_READ_RATE);
        sprintf(Buffer, "Rate Status 1 = 0x%X\r\n", Response_RateStat1);
        Serial.println(Buffer);
        sprintf(Buffer, "Rate Status 2 = 0x%X\r\n", Response_RateStat2);
        Serial.println(Buffer);
        sprintf(Buffer, "Acceleration Status = 0x%X\r\n", Response_AccStat);
        Serial.println(Buffer);
        sprintf(Buffer, "Common Status 1 = 0x%X\r\n", Response_ComStat1);
        Serial.println(Buffer);
        while (1); // Halt execution
    }
}

void loop()
{
    //    Response_Rate = SendRequest(REQ_READ_ACC_X);
    //    Serial.println(Response_Rate);
    //    delay(2000);
}

in MHO this is how your 'sendRequest' function should be written to receive the response bytes correctly:

uint32_t SendRequest(uint32_t Request)
{
    uint32_t Response = 0;
    uint8_t temp;
    
    digitalWrite(PIN_CSB, LOW);

    // Split Request into 8-bit sections and sending them one byte at a time
    temp = SPI.transfer(Request >> 24);
    
    temp = SPI.transfer(Request >> 16);
    Response = temp;
    
    temp = SPI.transfer(Request >> 8);
    Response = (Response << 8) | temp;
    
    temp= SPI.transfer(Request);
    Response = (Response << 8) | temp;
	
    temp= SPI.transfer(0x00); //to get final response to last request. this is dummy data (typically 0x00 or 0xFF)
    Response = (Response << 8) | temp;
	
    digitalWrite(PIN_CSB, HIGH);
    return (Response);
}

Hope that helps.

That is a 3.3V sensor, how are you powering it? Can you share a schematic?

sherzaad:
in MHO this is how your 'sendRequest' function should be written to receive the response bytes correctly:

Thank you for the reply.
Maybe I am wrong, but how sensor will know what to respond until whole 32 bit is not transmitted? E.g. to read the Rate 0x040000F7 must be completely send.

BJHenry:
That is a 3.3V sensor, how are you powering it? Can you share a schematic?

I have an evaluation board.

ESP32 SCC2230
DVDD 3V3
AVDD 3V3
DVSS GND
AVSS GND
CSB D5
MISO D19
MOSI D23
SCK D18
EXTESN D15

P.S.There is a code for NXP PLC11U14 chip if helps.

How did you have it connected when you tried with the Uno? Did you put 5V on the inputs or either of the VDD lines?

nebulae:
Thank you for the reply.
Maybe I am wrong, but how sensor will know what to respond until whole 32 bit is not transmitted? E.g. to read the Rate 0x040000F7 must be completely send.

Have a look at page 24 of the datasheet. The sensor won't start responding until the second request is sent. Think of it this way- the sensor won't know what request you are sending until the entire request is sent.

BJHenry:
How did you have it connected when you tried with the Uno? Did you put 5V on the inputs or either of the VDD lines?

No. I have used level shifter and 3V3 voltage regulator with separate 9V power supply.

BJHenry:
Have a look at page 24 of the datasheet. The sensor won't start responding until the second request is sent. Think of it this way- the sensor won't know what request you are sending until the entire request is sent.

Yes. That why I am using startup sequence as described in page 23.

nebulae:
No. I have used level shifter and 3V3 voltage regulator with separate 9V power supply.
Yes. That why I am using startup sequence as described in page 23.

Ok, that's good.

This could be a problem:

    pinMode(PIN_MOSI, INPUT);
    pinMode(PIN_MISO, OUTPUT);

MOSI is Master Out Slave In, so that pin should be an output. MISO should be the input.

This could be a problem:

    pinMode(PIN_MOSI, INPUT);

pinMode(PIN_MISO, OUTPUT);



MOSI is Master Out Slave In, so that pin should be an output. MISO should be the input.

Ugh. :o I have fixed that.

But SPI send receive routine is still wrong. I am only receiving 0xFFFFFFFF.

I think, I need to send dummy load to read SPI register. Something like this:

uint32_t SendRequest(uint32_t Request)
{
    uint32_t Response = 0x00;
    digitalWrite(PIN_CSB, LOW);
    // Send the request in 8-bit sections
    SPI.transfer(Request >> 24);
    SPI.transfer(Request >> 16);
    SPI.transfer(Request >> 8);
    SPI.transfer(Request);
    digitalWrite(PIN_CSB, HIGH);
    delay(1);
    digitalWrite(PIN_CSB, LOW);
    Response = SPI.transfer(0x00);
    Response = (Response << 8) | SPI.transfer(0x00);
    Response = (Response << 8) | SPI.transfer(0x00);
    Response = (Response << 8) | SPI.transfer(0x00);
    delay(1);
    digitalWrite(PIN_CSB, HIGH);
    return (Response);
}

Still does not work, but I am trying to figure out.

There might be some timing issues. I am running ESP32 at 40 Mhz. Now put "setClockDivider" to "SPI_CLOCK_DIV8" which makes 5 Mhz. Recommended is 8 Mhz, but I think it is still in range.
However some other tweaking is maybe necessary.

I have realized that the sensor is holding Slave Select and MISO pin high. Multimeter shows around 3.3 V. Contacted to the technical support.

@OP

Section-7.3.7 of the reading notes of this link on SPI Communication may help you to find the trick of exchanging 32-bit data between SPI-Master and SPI-Slave.

GolamMostafa:
@OP

Section-7.3.7 of the reading notes of this link on SPI Communication may help you to find the trick of exchanging 32-bit data between SPI-Master and SPI-Slave.

Everything works fine now. Only I need to make some improvements in my spaghetti code. I will share it later.
But PDF you provided in link is really helpful. Where is that from?

If the example that has been refereed to you is a helpful resource, then the labor of the person who has prepared this reading notes is greatly honored.

nebulae:
Everything works fine now. Only I need to make some improvements in my spaghetti code. I will share it later.
But PDF you provided in link is really helpful. Where is that from?

Hi @nebulae Can you share your final code? I can't force that sensor to work :wink: