Go Down

Topic: Send 32 bit SPI request and receive 32 bit response (Read 505 times) previous topic - next topic

nebulae

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.


Code: [Select]
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);
}

nebulae

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.


BJHenry

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.

nebulae

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

Code: [Select]

#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);
}

sherzaad

#5
Aug 15, 2019, 01:11 pm Last Edit: Aug 15, 2019, 01:14 pm by sherzaad
in MHO this is how your 'sendRequest' function should be written to receive the response bytes correctly:

Code: [Select]
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.

BJHenry

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

nebulae

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.

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.



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?

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.

nebulae

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.

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.

BJHenry

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:
Code: [Select]

    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.

nebulae

#11
Aug 15, 2019, 04:43 pm Last Edit: Aug 15, 2019, 04:44 pm by nebulae
Quote
This could be a problem:
Code: [Select]

    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.

nebulae

#12
Aug 15, 2019, 06:49 pm Last Edit: Aug 16, 2019, 12:25 pm by nebulae
I think, I need to send dummy load to read SPI register. Something like this:
Code: [Select]
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.

nebulae

#13
Aug 16, 2019, 10:23 am Last Edit: Aug 16, 2019, 10:23 am by nebulae
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.


nebulae

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.

Go Up