25LC1024 STORING 16BIT INTEGERS

Hello,

Really hope someone can help me as to where I have gone wrong in my code. I am a 25LC1024 micro chip and I'm trying to store a 16 bit integer value into 2 bytes and then reading the 2 bytes and putting them back together. Any help would be much appreciated, THANKS.

// 25LC1024 1Mbit SPI interface
//
// Device pin connections:
// 1 = CS (Chip Select) (from Arduino)  
// 2 = SO (Master In Slave Out) (from Arduino)
// 3 = +5V (WP) (from Arduino)
// 4 = 0V (Ground) (from Arduino)
// 5 = SI (Master Out Slave In) (from Arduino)
// 6 = SCK (from Arduino)
// 7 = +5V HOLD (from Arduino)
// 8 = +5V Vcc (from Arduino)
//
// This file uses the SPI library and produces higher oscillation rates than the manual methods
// for the Uno: SS/CS = pin 10, MOSI/SI = pin 11, SCK/clock = pin 13, MISO/SO = pin = 12
// 

#define WRITE 2
#define READ  3
#define WREN  6

#include <SPI.h>

unsigned int readvalue;

void setup()
{
  Serial.begin(9600);
  Serial.println("--------------");
  Serial.println(SS); // chip select
  Serial.println(MOSI); // master out, slave in
  Serial.println(MISO); // master in, slave out
  Serial.println(SCK); // clock
  Serial.println("--------------");
  
  // set up to match device datasheet
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2); // max clock is 20MHz, so can set high speed
  SPI.begin(); // sets up pin modes etc.
  
  // Enable writing
  digitalWrite(SS, LOW);
  SPI.transfer(WREN);
  digitalWrite(SS, HIGH);
  
  writing(50, 34);  //  data value, address
 
  readvalue = reading(34);
 
  Serial.print("Read Data = ");
  Serial.println(readvalue); 
  
}

void writing(unsigned int outval, unsigned long address)
{
  unsigned char low, high;
  unsigned long lowaddress = address + address;
  unsigned long highaddress = lowaddress + 1;
  
  low = outval & 0x00FF;
  high = (outval >> 8) & 0x00FF;
  
  // Write One Value to One Address
  digitalWrite(SS, LOW);
  SPI.transfer(WRITE); // write instruction
  SPI.transfer((lowaddress >> 16) & 255);
  SPI.transfer((lowaddress >> 8) & 255);
  SPI.transfer(lowaddress & 255);
  SPI.transfer(low);
  digitalWrite(SS, HIGH);
  
  // Write One Value to One Address
  digitalWrite(SS, LOW);
  SPI.transfer(WRITE); // write instruction
  SPI.transfer((highaddress >> 16) & 255);
  SPI.transfer((highaddress >> 8) & 255);
  SPI.transfer(highaddress & 255);
  SPI.transfer(high);
  digitalWrite(SS, HIGH);
  
  delay(100);
  
}

unsigned int reading (unsigned long address)
{
 
  unsigned char low, high;
  unsigned long lowaddress = address + address;
  unsigned long highaddress = lowaddress + 1;
  unsigned int finaloutput = 0;
 
  // Read One Value from One Address
  digitalWrite(SS, LOW); 
  SPI.transfer(READ); // read instruction
  SPI.transfer((lowaddress >> 16) & 255);
  SPI.transfer((lowaddress >> 8) & 255);
  SPI.transfer(lowaddress & 255);
  low = SPI.transfer(lowaddress);
  digitalWrite(SS, HIGH);
  
  digitalWrite(SS, LOW); 
  SPI.transfer(READ); // read instruction
  SPI.transfer((highaddress >> 16) & 255);
  SPI.transfer((highaddress >> 8) & 255);
  SPI.transfer(highaddress & 255);
  high = SPI.transfer(highaddress);
  
  digitalWrite(SS, HIGH);
  
  finaloutput = (high << 8) | low;
  
  return finaloutput;
}

void loop()
{
   
}

What is wrong?

Pete

Sorry, probably should have stated that too, haha.

The read value printed to the Serial Monitor is always random, usual a very high number such as 65330. Not sure the reading functions manages to do this. Both low and high values are always read as 255

Does that help indicate my issue?

When it always reads everything as 255 it usually indicates a wiring error.
But, if for any reason it doesn't write the value into the EEPROM, then you'll get 255 back anyway because that is the initial state of the erased EEPROM.

Pete

I've checked the wiring 3-4 times and it definitely right.

When I write one integer and to a single address the code works however when put through an array this is when the problem occurs. Trying to write an array of integers using a 'for while loop' to a number of addresses causes funny results. The value saved previously in the address is from writing one value at a time to a single address. If I haven't written something to a single address, thats when 65536 occurs? I think I've neated my code up thought but still having the same issue of writing an array one numbers and reading them back again

// 25LC1024 1Mbit SPI interface
//
// Device pin connections:
// 1 = CS (Chip Select) (from Arduino)  
// 2 = SO (Master In Slave Out) (from Arduino)
// 3 = +5V (WP) (from Arduino)
// 4 = 0V (Ground) (from Arduino)
// 5 = SI (Master Out Slave In) (from Arduino)
// 6 = SCK (from Arduino)
// 7 = +5V HOLD (from Arduino)
// 8 = +5V Vcc (from Arduino)
//
// This file uses the SPI library and produces higher oscillation rates than the manual methods
// for the Uno: SS/CS = pin 10, MOSI/SI = pin 11, SCK/clock = pin 13, MISO/SO = pin = 12
// 

#define WRITE 2
#define READ  3
#define WREN  6

#include <SPI.h>

unsigned int values[10] = {0,4,6,7,3,2,4,5,5,7};
unsigned long masteraddress = 5, time1, time2, samplerate, readtime;
float timeseconds;
unsigned int readvalue;

byte invalue, invalue2;

void setup()
{
  Serial.begin(9600);
  
  // set up to match device data sheet
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2); // max clock is 20MHz, so can set high speed
  SPI.begin(); // sets up pin modes etc.
  
  // Enable writing
  digitalWrite(SS, LOW);
  SPI.transfer(WREN);
  digitalWrite(SS, HIGH);
  
  writing(masteraddress, 666); // address, data value

  Serial.print("Read Time = ");
 
  time1 = micros(); // Gather time in micro seconds before reading 10,00 values
  for(int i = 0; i < 10000; i++)
  {
  readvalue = reading(i);
  }
  time2 = micros(); // Gather time in micro seconds after reading 10,00 values
  
  readtime = time2 - time1; // calculates time in micro seconds to read 10,000 values
  Serial.println(readtime);
  
  timeseconds = readtime / 1000000; // Converts micro seconds into seconds
  samplerate = 10000 / timeseconds; // Sample rate = Number of values read / Length of time in seconds
  
  Serial.print("Time in seconds  = ");
  Serial.println(timeseconds);
  
  Serial.print("Sample rate  = ");
  Serial.println(samplerate);
  
  Serial.print("Read value = ");
  Serial.println(readvalue,DEC);
}

void writing(unsigned long address, unsigned int inputval)
{  
  unsigned char low, high;
  unsigned long lowaddress = address * 2;
  unsigned long highaddress = lowaddress + 1;
  
  low = inputval & 0x00FF;
  high = (inputval >> 8) & 0x00FF;
  
  digitalWrite(SS, LOW);
  SPI.transfer(WRITE); // write instruction
  
  // Write low byte first
  SPI.transfer((lowaddress >> 16) & 255);
  SPI.transfer((lowaddress >> 8) & 255);
  SPI.transfer(lowaddress & 255);
  SPI.transfer(low);
  
  // Write high byte second
  SPI.transfer((highaddress  >> 16) & 255);
  SPI.transfer((highaddress >> 8) & 255);
  SPI.transfer(highaddress & 255);
  SPI.transfer(high);
  
  digitalWrite(SS, HIGH); 
}

unsigned int reading(unsigned long address)
{

  unsigned char low, high;
  unsigned long lowaddress = address * 2;
  unsigned long highaddress = lowaddress + 1;
  unsigned int finaloutput;
  
  digitalWrite(SS, LOW); 
  SPI.transfer(READ); // read instruction
 
  // Read the low byte first
  SPI.transfer((lowaddress >> 16) & 255);
  SPI.transfer((lowaddress >> 8) & 255);
  SPI.transfer(lowaddress & 255);
  low = SPI.transfer(lowaddress);
  
  // Read the high byte second
  SPI.transfer((highaddress >> 16) & 255);
  SPI.transfer((highaddress >> 8) & 255);
  SPI.transfer(highaddress & 255);
  high = SPI.transfer(highaddress);
  
  finaloutput = (high << 8) | low;
  
  digitalWrite(SS, HIGH);
  
  return finaloutput;  
}
void loop()
{
   
}

I don't think you are reading or writing them correctly.
Try writing the two bytes like this:

  digitalWrite(SS, LOW);
  SPI.transfer(WRITE); // write instruction
  
  // Write low byte first
  SPI.transfer((lowaddress >> 16) & 255);
  SPI.transfer((lowaddress >> 8) & 255);
  SPI.transfer(lowaddress & 255);
  SPI.transfer(low);
  SPI.transfer(high);
  
  digitalWrite(SS, HIGH);

and do the same thing with reading them.

Pete

Pete,

I've decided to try and do a page write instead and it worked and with the help you have given me I've adapted it however this code did work but all of sudden stopped working.

// 25LC1024 1Mbit SPI interface
//
// Device pin connections:
// 1 = CS (Chip Select) (from Arduino)  
// 2 = SO (Master In Slave Out) (from Arduino)
// 3 = +5V (WP) (from Arduino)
// 4 = 0V (Ground) (from Arduino)
// 5 = SI (Master Out Slave In) (from Arduino)
// 6 = SCK (from Arduino)
// 7 = +5V HOLD (from Arduino)
// 8 = +5V Vcc (from Arduino)
//
// This file uses the SPI library and produces higher oscillation rates than the manual methods
// for the Uno: SS/CS = pin 10, MOSI/SI = pin 11, SCK/clock = pin 13, MISO/SO = pin = 12
// 

#define WRITE 2
#define READ  3
#define WREN  6

#define SSMEMORY 9

#include <SPI.h>

void setup()
{
  Serial.begin(9600);
  pinMode(SSMEMORY, OUTPUT);
  digitalWrite(SSMEMORY, HIGH);
  
  Serial.println("--------------");
  Serial.println(SSMEMORY); // chip select
  Serial.println(MOSI); // master out, slave in
  Serial.println(MISO); // master in, slave out
  Serial.println(SCK); // clock
  Serial.println("--------------");
  
  // set up to match device datasheet
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2); // max clock is 20MHz, so can set high speed
  SPI.begin(); // sets up pin modes etc.
  
  for (int i = 0; i < 5; i++)
  {
  writing(i, i);  //  data value, address
  } 

  delay(100);
 
  Serial.print("\n"); 

  for(unsigned long i = 0; i < 5; i++)
  {
  unsigned int readvalue = reading(i);
  
  Serial.print("READ = ");
  Serial.println(readvalue);
  Serial.print("\n");
  }
  
}

void writing(unsigned int outval, unsigned long address)
{
  unsigned char low, high;
  address = address + address;
  
  low = outval & 0x00FF;
  high = (outval >> 8) & 0x00FF;
  
  Serial.print("Write LOW Data = ");
  Serial.println(low, DEC); 
  
  Serial.print("Write HIGH Data = ");
  Serial.println(high, DEC); 
  
  // Write One Value to One Address
  // Enable writing
  digitalWrite(SSMEMORY, LOW);
  SPI.transfer(WREN);
  digitalWrite(SSMEMORY, HIGH); 
  
  digitalWrite(SSMEMORY, LOW);
  SPI.transfer(WRITE); // write instruction
  SPI.transfer((address >> 16) & 255);
  SPI.transfer((address >> 8) & 255);
  SPI.transfer(address & 255);
  SPI.transfer(low);
  SPI.transfer(high);
  digitalWrite(SSMEMORY, HIGH);
}

unsigned int reading (unsigned long address)
{
 
  unsigned char low, high;
  address = address + address;
  unsigned int finaloutput;
 
  // Read One Value from One Address
  digitalWrite(SSMEMORY, LOW); 
  SPI.transfer(READ); // read instruction
  
  SPI.transfer((address >> 16) & 255);
  SPI.transfer((address >> 8) & 255);
  SPI.transfer(address & 255);
  low = SPI.transfer(0);
  high = SPI.transfer(0);
  digitalWrite(SSMEMORY, HIGH);
  
  Serial.print("Read LOW Data = ");
  Serial.println(low, DEC); 
  
  Serial.print("Read HIGH Data = ");
  Serial.println(high, DEC); 
  
  finaloutput = (high << 8) | low;
  
  return finaloutput;
}

void loop()
{
   
}

In my setup I am also trying to use a DAC. Once I managed to get my code working for the DAC through using digital pin 9 as its OUTPUT for chip select, the pin 10 did not work any more for the external memory.

The result given for the the read value is always 65536 at every address. WHAT IS HAPPENING? I didn't change anything. I have checked the wiring... again and again but I swear its all correct.

Do you see any bugs in my code?

Thanks again for all your help.

I'm pretty sure you have to call SPI.begin before doing anything else. Otherwise your setup of bitorder etc. will be overridden by whatever default is set by SPI.begin.

Pete

The value of 65535 (not 65536?) is a 16-bit word with all ones which is what you get if you read two bytes which have been erased (or deliberately set to 0xFFFF).

Write timing can be critical with EEPROMS. I've had some fun recently getting an I2C 24LC1026 working properly.
The 25lc1024 datasheet has this about writing:

While the write is in progress, the Status Register may
be read to check the status of the WPEN, WIP, WEL,
BP1 and BP0 bits (Figure 2-6). A read attempt of a
memory array location will not be possible during a
write cycle. When the write cycle is completed, the
write enable latch is reset.

It is possible that it is still writing one byte when you try to write or read another. After the data has been written you'll have to check the status register to be sure that the write has completed.

Pete