Reading Serial Flash Manufacture/Device ID via SPI.transfer

Hello,

I could use some help troubleshooting. I'm trying to read the manufacturer and device ID from a W25Q128FV serial flash using SPI on an Arduino Due.

The flash's datasheet reads:

"The instruction is initiated by driving the /CS pin low and shifting the instruction code "90h" followed by a 24-bit address (A23-A0) of 000000h. After which, the Manufacturer ID for Winbond (EFh) and the Device ID are shifted out on the falling edge of CLK with most significant bit (MSB) first as shown in Figure 39."

My first stab at the code is:

#include <SPI.h>

#define SERIAL_BAUD 9600
#define MEMORY 4 // Chip select pin

void setup()
{
  Serial.begin(SERIAL_BAUD);
  Serial.print("Start...");

  SPI.begin(MEMORY);
  SPI.setClockDivider(MEMORY, 21);
  SPI.setDataMode(MEMORY, SPI_MODE0);

  SPI.transfer(MEMORY, 0x90, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x000000, SPI_CONTINUE);
  byte response1 = SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  byte response2 = SPI.transfer(MEMORY, 0x00);

  Serial.print("Response: ");
  Serial.println(response1);
  Serial.println(response2);
}

void loop()
{
}

The response I get is always 255, 255.

I have a logic analyzer, and here's what it is showing:

There's nothing after that.

It appears that I'm shifting in the instructions correctly, but there's probably something wrong with my code that reads the response. I'm actually a little confused about that, too. It seems like I need to transfer some instructions to the SPI Flash, then read back a response. I need to send => send => receive => receive, but that doesn't seem to be an option with SPI.transfer().

I'm probably wrong and confused, so any help would be much appreciated.

Cheers,
Bret

Your SPI transaction looks good, except that the chip is not responding. Assuming that the clock speed is in spec, we are looking for a hardware problem om the Flash side.

Did you set HOLD and/or RESET high?

Hi clone45

I think you may not be sending out enough bytes before trying to read the 2 byte response. So CS is going inactive too soon.

The SPI.transfer() statement sends one byte only.

Try this change to your code:

  SPI.transfer(MEMORY, 0x90, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  byte response1 = SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  byte response2 = SPI.transfer(MEMORY, 0x00);

Regards

Ray

Ray,

You were correct! Thanks so much! My final code looks like this:

#include <SPI.h>

#define SERIAL_BAUD 9600
#define MEMORY 4 // Chip select pin

void setup()
{
  Serial.begin(SERIAL_BAUD);
  Serial.print("Start...");

  SPI.begin(MEMORY);
  SPI.setClockDivider(MEMORY, 21);
  SPI.setDataMode(MEMORY, SPI_MODE0);

  SPI.transfer(MEMORY, 0x90, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  byte response1 = SPI.transfer(MEMORY, 0x00, SPI_CONTINUE);
  byte response2 = SPI.transfer(MEMORY, 0x00);

  Serial.print("Response: ");
  Serial.println(response1);
  Serial.println(response2);
}

void loop()
{
}

The output is:

Start...Response: 239
23

That output is correct.

Cheers,
Bret