Read operation over 3-wire SPI with 2 byte protocol?

The sensor I'm trying to communicate with uses 3-wire SPI (MOSI is tied to SDIO/MISO through a resistor):

| Sensor pin | uC pin |
|------------|--------|
|   NCS      |  SS    |
|   SDIO     |  MISO  |
|   SCLK     |  SCLK  |

It uses a 2-byte protocol, where byte0[7] = R/W bit and byte0[6:0] = address, and byte1 = data. Because there's only one data line, I'm unsure whether the built-in SPI library is compatible with my device.

This is my current function to execute a read operation; data=0x0000 (read at address = 0b0000000):

void initSPI() {
  vspi = new SPIClass(VSPI);
  vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_CS);
  pinMode(vspi->pinSS(), OUTPUT);  //VSPI SS
  digitalWrite(vspi->pinSS(), HIGH);
}

uint8_t spiCommand(SPIClass *spi, uint16_t data) {
  uint8_t addrByte = (uint8_t)(data >> 8);
  uint8_t dataByte = (uint8_t)(data & 0xFF);

  spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE3));
  digitalWrite(spi->pinSS(), LOW);
  spi->transfer(addrByte);
  pinMode(VSPI_MISO, INPUT);
  uint8_t dataRet = spi->transfer(0);
  digitalWrite(spi->pinSS(), HIGH);
  spi->endTransaction();
  pinMode(VSPI_MISO, OUTPUT);
  
  return dataRet;
}

uint16_t compileSPIProtocol(uint8_t rw, uint8_t addr, uint8_t data) {
  uint16_t protocol = 0x0;
  protocol = (rw << 7) | addr;
  protocol = protocol << 8;
  protocol = protocol | data;
  return protocol;
}

The datasheet indicates that the host controller should release control of the SDIO (MOSI) line to the sensor on the falling edge of the last address bit. That's what the line pinMode(VSPI_MISO, INPUT); is supposed to do, but I'm not actually certain whether this the correct method.

The expected value of the register at 0x00 (product ID) should be 0x31, but is currently outputting 0x00.

Any ideas?

Perhaps the information below will bring some inspiration (copied from How to use Arduino in SPI 3-wire ? - #37 by westfw):

From the experiences I've had using 3 wire SPI (most recently with an MCP4161 digital pot), the standard SPI library Just Works with 3 wire SPI.

Just for clarification, are you sure it's an SPI interface. I only ask because your byte0 has a very similar structure to the first byte after an I2C start condition on an I2C bus.

Can you provide a link to a datasheet for the device.

Yes it is SPI, but I cannot provide a datasheet because its under NDA. SPI commonly uses the first byte for R/W bit and address no?

No. But I2C does.

The datasheet section header says "3-wire SPI Serial Interface". Though, right below that it says "half-duplex protocol", so I'm beginning to think you are correct.

The only device I've come across that is SPI but uses a first byte like that is an MCP23S17 I/O expander.

There is another SPI type interface. Have a look at AN-877 from Analog Devices. It's an app note about interfacing to high speed ADCs via SPI. Does that resemble what's described in your devices datasheet.

I think this is half duplex SPI which I seem to recall has a resistor - around 10K I think - between MOSI and MISO as shown in the schematic that @van_der_decken provided in post #2.

Apart from that resistor, I don't think there's any difference and the code works just like standard SPI - i.e. you don't need to change your MISO pin from input to output.

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