I salvaged a flash chip from a digital photo frame this morning. I found the datasheet and made a sketch that should write a binary 01010101 to address 1000000 on the chip, then read it and output it to the serial monitor. However, It always returns 0. No matter what I read, address, status register, anything, it always comes up with 0. I have verified my wiring. I have spi through voltage dividers to the chip, with vcc to 3.3v and vss to GND. The chip is decoupled. That only leaves my code.
// inslude the SPI library:
#include <SPI.h>
// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 20;
long address1 = 1000000;
void setup() {
Serial.begin(9600);
SPI.setBitOrder(MSBFIRST);
// set the slaveSelectPin as an output:
pinMode (slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
digitalWrite(slaveSelectPin,LOW);
SPI.transfer(6);
digitalWrite(slaveSelectPin,HIGH);
Write(address1, B01010101);
}
void loop() {
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
Serial.println(Read(address1),BIN);
delay(10000);
}
void Write(long address, byte value){
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
SPI.transfer(2);
SPI.transfer((address) & B11111111);
SPI.transfer((address >> 8) & B11111111);
SPI.transfer((address >> 16) & B11111111);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
}
byte Read(long address)
{
byte value;
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
SPI.transfer(3);
SPI.transfer((address) & B11111111);
SPI.transfer((address >> 8) & B11111111);
SPI.transfer((address >> 16) & B11111111);
value = SPI.transfer(0);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
return value;
}
Is this what is causing my problem? is the arduino doing this at the same time?
(from the datasheet)
In the case of a Page Program (PP), Sector Erase (SE), Block Erase (BE), Chip Erase (CE), Write Status
Register (WRSR), Write Enable (WREN), Write Disable (WRDI) or Deep Power-down (DP) instruction,
Chip Select (CS#) must be driven High exactly at a byte boundary, otherwise the instruction is rejected,
and is not executed. That is, Chip Select (CS#) must driven High when the number of clock pulses after
Chip Select (CS#) being driven Low is an exact multiple of eight. For Page Program, if at any time the
input byte is not a full byte, nothing will happen and WEL will not be reset.
I made code that reads the addresses and status register and prints them via serial. You can tell the results are gibberish because the status register byte should stay constant. Here is the data in this format: address -- status register -- Address byte value
#include <SPI.h>
byte writeEnable = 6;
const int slaveSelectPin = 20;
long address1 = 0000000;
void setup()
{
Serial.begin(9600);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV128);
SPI.setDataMode(0);
// set the slaveSelectPin as an output:
pinMode (slaveSelectPin, OUTPUT);
digitalWrite(slaveSelectPin,HIGH);
// initialize SPI:
SPI.begin();
digitalWrite(slaveSelectPin,LOW);
SPI.transfer(writeEnable);
digitalWrite(slaveSelectPin,HIGH);
delay(1000);
Write(address1, B01010101);
delay(1000);
}
void loop() {
// send in the address and value via SPI:
for(long a=0; a<1000000; a++){
Serial.print(a);
Serial.print(" -_- ");
Serial.print(ReadSR(),BIN);
Serial.print(" -_- ");
Serial.println(Read(a),BIN);
delay(50);
}
}
void Write(long address, byte value){
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
SPI.transfer(2);
SPI.transfer((address >> 16) & B11111111);
SPI.transfer((address >> 8) & B11111111);
SPI.transfer((address) & B11111111);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
}
byte Read(long address)
{
byte value;
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
SPI.transfer(3);
SPI.transfer((address >> 16) & B11111111);
SPI.transfer((address >> 8) & B11111111);
SPI.transfer((address) & B11111111);
value = SPI.transfer(0);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
return value;
}
byte ReadSR()
{
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
SPI.transfer(5);
byte value = SPI.transfer(0);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
return value;
}
I believe you need to declare D10, the SS pin associated with the internal SPI hardware, as an output also, otherwise I think the chip may think it is an SPI slave, vs being the master. You can still use this for chip select.
const int slaveSelectPin = 20;
You are using a Mega? There is no 20 on an Uno. I think SS on the Mega is 50, but confirm that.
Heres what I have so far:
(keep in mind that all of the commands that don't work rely on write enable to be executed first, so that could be the only problem)
Commands that work:
Write enable
Write
Read
Read status register
Fast read
Enter/exit deep power down
Write Status Register
Chip Erase
Sector/block erase
Commands that I haven't tried yet:
Read manufacturer/device ID
Read ID
Enter OTP mode
I will update this as I go. Once I get everything, I will release a library if asked
Edit1
Fast read works
I believe the deep power down stuff works, but I'm not quite sure
Edit2
Verified that deep power down stuff works
Block and sector erase dont work
EDIT4
Erases now work. Probably going to skip ID stuff and OTP for now. Write status register should work, not tested yet.
And forgot to mention, this all started to work after a power cycle on the chip
Aparrenty chips like this are everywhere. I found a pcb from a cd drive and it had a chip that was the exact same except it had twice the flash and supports quad spi. Can I utilize quad spi with arduino?