Any SPI / Flash experts out there?

Hi All…

I am trying to get my Uno to talk to a Winbond 8MB Flash chip via SPI. I checked the leading edge/falling edge stuff and the other things that need to be considered on SPI. The code below simply tries to read the status register, set write enable, then read the status register again. It then looks for a change in the status register.

The code below executes the same whether the flash chip is hooked up or not. I’m pretty sure I have it hooked up right. Its pretty simple actually. I’m hopeing someone can help me find the issue before I decide my chip is bad. The data sheet for the chip is referenced int eh code, in a comment.


// Some code to play with the Winbond flash

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//SCK
#define SLAVESELECT 10//SS
#define WP 8//Write protect

// Opcodes
// Taken from Winbond datasheet:

#define WREN 0x06 // Write Enable
#define WRDI 0x04 // Write Disable
#define RDSR1 0x05 // Read Status Register 1
#define RDSR2 0x35 // Read Status Register 2
#define WRSR 0x01 // Write Status Register
#define READ 0x03 // Read Data
#define READID 0x90 // Read Manufacturer / Device ID
#define READUNID 0x4B // Read Unique ID Number (factory set 64-bit ID) - optional feature on chip

void setup()
  pinMode(DATAIN, INPUT);
  pinMode(WP, OUTPUT);
  digitalWrite(SLAVESELECT, HIGH); //Disable device
  digitalWrite(WP, HIGH); // Disable write protect

  // Set CPUs SPI status register to 0101 0000
  SPCR = (1 << SPE) | (1 << MSTR);
  // Read any junk data from status registers
  byte clr;
  clr = SPSR;
  clr = SPDR;
  byte readA = 0;
  byte readB = 0;
  byte readC = 0;
  Serial.print("Reading status register\r\n");
  digitalWrite(SLAVESELECT, LOW); 
  readA = spiTransfer(RDSR1);
  digitalWrite(SLAVESELECT, HIGH); 


  Serial.print("Sending write enable\r\n");
  digitalWrite(SLAVESELECT, LOW); 
  byte response = spiTransfer(WREN);
  digitalWrite(SLAVESELECT, HIGH); 

  Serial.print("Reading status register\r\n");

  digitalWrite(SLAVESELECT, LOW); 
  readB = spiTransfer(RDSR1);
  digitalWrite(SLAVESELECT, HIGH); 

  if(readA != readB)
    Serial.print("Values differ\r\n");
    Serial.print("Values the same\r\n");

void loop()

byte spiTransfer(volatile byte data)
  SPDR = data;
  while (!(SPSR & (1<<SPIF)))
  return SPDR;


I had the same problem, using the SPI library though, and found that I wasn't toggling chip select, I thought the SPI library would do that for me.

My /CS is on pin 10 (11,12,13 set the normal way)

: :

SPI.begin(); SPI.setDataMode(0); SPI.setBitOrder(MSBFIRST);

byte r1, r2, r3;

digitalWrite(10, LOW); SPI.transfer(0x9f); r1 = SPI.transfer(0); r2 = SPI.transfer(0); r3 = SPI.transfer(0); digitalWrite(10, HIGH);

: :

The results were EF 40 14 in r1, r2, r3 respectively.

Thx, PJT

I was wondering about the 3.3V requirement of the flash: the signals from the Uno are 5V high. That might require a level shifter. Not sure.

Yes it does. The 5v into the SD will probably give it a hernia, in the other direction 3v3 into the Arduino will probably work as a logic high minimum is 3v.


Thanks Rob. I modified my original post with the solution and deleted the 5V line. I'm still overdriving the inputs (I have 100+ units to experiment with), but probably just lucky so far. Off to digikey to find a level shifter.