Electronic – arduino – 28C64 EEPROM Programming Using Arduino

arduinoeeprom

I am working on a Z80 computer and needed to write data to an EEPROM. I am using the Xicor 28C64AP-25 chip (datasheet). I wrote a program for the Arduino Uno that writes data to the first 4 addresses and then reads the data back. Since I am only using the first three address pins, the rest are tied low. Here is my code, sorry if it seems too cluttered:

#define WE 11
#define OE 12
#define CE 13
#define NUM_ADDR 3
int DP[8] = {A0, A1, A2, A3, A4, A5, 2, 3};
int AP[] = {4, 5, 6};
byte data[] = {0x3E, 0xAA, 0xD3, 0x00, 0xC3, 0x00, 0x00};
void setupDataBus(int mode) {
  for (int i = 0; i < 8; i++) {
    pinMode(DP[i], mode);
  } 
}
void setupControlPins(int mode) {
  pinMode(WE, mode);
  pinMode(OE, mode);
  pinMode(CE, mode);
}
void setupAddressBus(int mode) {
  for (int i = 0; i < NUM_ADDR; i++) {
    pinMode(AP[i], mode);
  } 
}
void writeByte(int address, byte data) {
  setupDataBus(OUTPUT);
  setupAddressBus(OUTPUT);
  setupControlPins(OUTPUT);
  Serial.print("Write Byte: ");
  for (int b = 0; b < 7; b++) {
     digitalWrite(AP[b], bitRead(address, b));

  } 
  Serial.print(address, HEX);
  Serial.print(", ");
  Serial.print(data, HEX);
  Serial.println();
  delay(1);
  // Enable write
  digitalWrite(OE, HIGH);
  delay(1);
  digitalWrite(CE, LOW);
  delay(1);
  delay(10);
  for (int b = 0; b < 8; b++) {
    digitalWrite(DP[b], bitRead(data, b));
  }
  unsigned long time_i, time_f;
  time_i = micros();
  // Start write
  digitalWrite(WE, LOW);
  // End write
  digitalWrite(WE, HIGH);
  time= micros();
  Serial.println(time_f-time_i, DEC);
  delay(1);
  digitalWrite(OE, LOW);
  delay(1);
  digitalWrite(CE, HIGH);
  delay(1);

}
byte readByte(int address) {
  setupDataBus(INPUT);
  setupAddressBus(OUTPUT);
  setupControlPins(OUTPUT);
  byte val;
  digitalWrite(WE, HIGH);
  delay(1);
  digitalWrite(CE, HIGH);
  delay(1);
  digitalWrite(OE, HIGH);
  delay(1);
  Serial.print("Read Byte: ");
  for (int b = 0; b < 7; b++) {
     digitalWrite(AP[b], bitRead(address, b));
  }
  Serial.print(address, HEX);  
  Serial.print(", ");
  delay(1);
  digitalWrite(WE, HIGH);
  delay(1);
  digitalWrite(CE, LOW);
  delay(1);
  digitalWrite(OE, LOW);
  delay(1);

  for (int b = 0; b < 8; b++) {
     bitWrite(val, b, digitalRead(DP[b]));
  } 
  Serial.print(val, HEX);
  delay(1);
  digitalWrite(OE, HIGH);
  delay(1);
  digitalWrite(CE, HIGH);
  delay(1);
  digitalWrite(WE, HIGH);
  Serial.println();
  return val;
}
void setup() {
  setupDataBus(OUTPUT);
  setupAddressBus(OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(CE, OUTPUT);
  Serial.begin(9600);
  }
  void loop() {
  // init
  digitalWrite(OE, HIGH);
  digitalWrite(CE, HIGH);
  digitalWrite(WE, HIGH);
  Serial.println("Initializing pins for write...");
  delay(1000);
  for (int i = 0; i < sizeof(data); i++) {
    writeByte(i, data[i]);
  }
  for (int i = 0; i < sizeof(data); i++) {
    readByte(i);
  }
  while(true);
}

All those delays are just to make sure I'm not going too fast for the EEPROM.
I can tell via some LEDs that the Arduino is outputing the right data onto the I/O pins of the EEPROM, but when I read the data back, all I get is 0xFF. Here is the serial output.

Initializing pins for write...
Write Byte: 0, 3E
/WE enable time: 12
Write Byte: 1, AA
/WE enable time: 12
Write Byte: 2, D3
/WE enable time: 12
Write Byte: 3, 0
/WE enable time: 12
Write Byte: 4, C3
/WE enable time: 12
Write Byte: 5, 0
/WE enable time: 12
Write Byte: 6, 0
/WE enable time: 12
Read Byte: 0, FF
Read Byte: 1, FF
Read Byte: 2, FF
Read Byte: 3, FF
Read Byte: 4, FF
Read Byte: 5, FF
Read Byte: 6, FF

I have tested an earlier version of the above program with a static RAM chip and everything works great. It just doesn't work with the EEPROM.

Any help would be much appreciated.

Best Answer

The device has 13 address pins, which should specify an address in binary from 0x0000 to 0x1FFF. You have not indicated that you are doing anything with them?

Also, I would suggest that you should write a writebyte procedure which sets all address and data wires to output and puts proper values on them, ensures WE and OE are deasserted, asserts CE, asserts and release WE, and releases CE, and a readbyte procedure which sets all address wires to output and puts proper values on them, sets all data wires to input, asserts CE and OE, samples all the data wires, and releases CE and OE. That will make the remainder of your code much more readable.