write/read from a SST25VF080B flash memory with spi

Hey guys

I am currently using the ARDUINO UNO to write and read from a flash memory using SPI bus. I think i might have an issue with the read because i am not reading what i wrote. Here is the datasheet of the memory that i am using http://docs-europe.electrocomponents.com/webdocs/1385/0900766b81385d2b.pdf

And here is my code

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN 6
#define WRDI 4
#define RDSR 5
#define WRSR 1
#define Read 3
#define Byte-Program 2
#define Chip-Erase 60

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
int address=0;
//data buffer
char buffer [128];

void fill_buffer()
{
for (int I=0;I<128;I++)
{
buffer[2]=0x01;
}
}

char spi_transfer(volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
return SPDR; // return the received byte
}

void setup()
{
Serial.begin(9600);

pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
digitalWrite(SLAVESELECT,HIGH); //disable device

SPCR = (1<<SPE)|(1<<MSTR);
clr=SPSR;
clr=SPDR;
delay(10);
fill_buffer();

digitalWrite(SLAVESELECT,LOW);
spi_transfer(WREN); //write enable
digitalWrite(SLAVESELECT,HIGH);
delay(10);
digitalWrite(SLAVESELECT,LOW);
spi_transfer(0x02); //write instruction
address=0;
spi_transfer((char)(address>>8)); //send MSByte address first
spi_transfer((char)(address)); //send LSByte address
//write 128 bytes
for (int I=0;I<128;I++)
{
spi_transfer(buffer*); //write data byte*

  • }*

  • digitalWrite(SLAVESELECT,HIGH); //release chip //fill buffer with data*

  • delay(3000);*

  • Serial.print(‘h’);*

  • Serial.print(‘i’);*

  • Serial.print(’\n’);//debug*

  • delay(1000);*
    }
    byte read_eeprom(int EEPROM_address)
    {

  • //READ EEPROM*

  • int data;*

  • digitalWrite(SLAVESELECT,LOW);*

  • spi_transfer(0x03); //transmit read opcode*

  • spi_transfer((char)(EEPROM_address>>8)); //send MSByte address first*

  • spi_transfer((char)(EEPROM_address)); //send LSByte address*

  • data = spi_transfer(0xFFFFFF); //get data byte*

  • digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer*

  • return data;*
    }
    void loop()
    {

  • eeprom_output_data = read_eeprom(address);*

  • Serial.print(address);*

  • Serial.print("…");*
    Serial.print(eeprom_output_data);

  • Serial.print(’\n’);*

  • address++;*

  • if (address == 128)*

  • address = 0;*

  • delay(500);*

//pause for readability
}

spi_transfer((char)(address>>8)); //send MSByte address first

Shift by a happy face? What a great idea.

Perhaps the other byte should be shifted by a frowny face.

Actually its spi_transfer((char)(adress>>8);

the happy face is the number eight

the happy face is the number eight

Like this 8?

No. Actually it is 8 followed by a ).

The point was that you did not post your code correctly, or it would not have smiley faces and italics.

Read the threads at the top of the forum, and learn how to post code correctly. (That involves clicking the icon on the left on the top row - the one with </> - before pasting the code.)

PaulS:
Shift by a happy face? What a great idea.

Perhaps the other byte should be shifted by a frowny face.

That is Just Wrong!, :slight_smile: I’ve heard o sh~~faced, but never Happy Faced.

Chuck.

marcelino1988:
Hey guys

I am currently using the ARDUINO UNO to write and read from a flash memory using SPI bus. I think i might have an issue with the read because i am not reading what i wrote. Here is the datasheet of the memory that i am using http://docs-europe.electrocomponents.com/webdocs/1385/0900766b81385d2b.pdf

And here is my code

#define DATAOUT 11//MOSI

#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define Read  3
#define Byte-Program 2
#define Chip-Erase 60

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
int address=0;
//data buffer
char buffer [128];

void fill_buffer()
{
 for (int I=0;I<128;I++)
 {
   buffer[2]=0x01;
 }
}

char spi_transfer(volatile char data)
{
 SPDR = data;                    // Start the transmission
 while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
 {
 };
 return SPDR;                    // return the received byte
}

void setup()
{
 Serial.begin(9600);

pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK,OUTPUT);
 pinMode(SLAVESELECT,OUTPUT);
 digitalWrite(SLAVESELECT,HIGH); //disable device
 
 SPCR = (1<<SPE)|(1<<MSTR);
 clr=SPSR;
 clr=SPDR;
 delay(10);
  fill_buffer();

digitalWrite(SLAVESELECT,LOW);
 spi_transfer(WREN); //write enable
 digitalWrite(SLAVESELECT,HIGH);
 delay(10);
 digitalWrite(SLAVESELECT,LOW);
 spi_transfer(0x02); //write instruction

First problem, command 2 is SINGLE byte write command.

This is a 5 byte sequence, 0x02,((ADDR >> 16)&0xff),((ADDR>>8)&0xFF),(ADDR&0xFF),DATA_Byte

marcelino1988:

  address=0;

spi_transfer((char)(address>>8));   //send MSByte address first
 spi_transfer((char)(address));      //send LSByte address

second problem, Address need 3 bytes (24bits)

Here is a better block write code

/* addr only specifies A23..A1, A0 is always 0, the first byte of data is always
   written at A23..A1,0  (a word Address)
   One additional proviso, If the memory pointed to by addr is not blank (0xff) the write
   command will not actually store what you wrote.  any bit that was 0 before the write
   command will still be 0 (zero) after the write command.  This means that if a memory cell
   currently contains B11110000 and you try to write B01110001 into it, the cell will actually 
   contain B01110000.  The '1's can be change to '0's but, not the reverse.  If you need to change
   a 0 to a 1, you have to use the SECTOR Erase Command and IT WILL ERASE the WHOLE sector.
  (4096 bytes at a time).

*/

uint16_t writeBlock(uint8_t cs, unsigned long addr, uint8_t * data, uint16_t len){
digitalWrite(cs,LOW);
spi_transfer(WREN);
digitalWrite(cs,HIGH);
uint16_t cnt=0;
digitalWrite(cs,LOW);
spi_transfer(0xAD); // Auto Address Increment Programming command

spi_transfer((addr>>16)&0xff); //most significant byte of address

spi_transfer((addr>>8)&0xff);  // middle byte of address

spi_transfer(addr&0xff);          // Least significant byte of address


while(cnt<len){
  spi_transfer(data[cnt++]);
  }
digitalWrite(cs,HIGH);
uint8_t ready=0;
do{
  digitalWrite(cs,LOW);
   spi_transfer(0x05); // read status byte cmd
   ready=spi_transfer(0); // read status byte
   digitalWrite(cs,HIGH);
  }while(!((ready&0x80)==0x80)); // wait for program cycle to complete
return cnt;
}

Chuck.