7
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ One thing that is missing is on page 7 of the datasheet, it states that you need to write a sequence of codes to disable write-protection. \$\endgroup\$ – user121381 Aug 21 '16 at 20:46
4
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the response, @supercat. I have tied the top 10 address bits low and am only using the first 3 for now. I have edited my question. I understand the benefits of separating the code into subroutines and will probably do this, but for now I am just trying to get the byte write working. \$\endgroup\$ – Matthew R. Mar 26 '13 at 22:04
1
\$\begingroup\$

Looking at the datasheet on page 12 it shows a timing diagram and Chip Enable Access Time can be up to 250nS. If using an AVR with a clock >= 4MHz you may be under this time and need a few small delays in your read code, for a start maybe even try long delays like you've done with the write code until you know it's working.

The same diagram shows CE being asserted followed by OE for a read cycle. I'd recommend following that same sequence and also change your write sequence to follow the diagram on the following page.

\$\endgroup\$
  • \$\begingroup\$ I added 500ms delays between every control pin change and made sure the order was consistent with the datasheet, but still no luck. Do EEPROMs require precise timing, meaning that I could now be going to slow for the chip? Thanks. \$\endgroup\$ – Matthew R. Mar 27 '13 at 13:18
  • \$\begingroup\$ @MatthewR.: The timings for this particular EEPROM aren't super-critical, but it has a timer which starts when the first byte is written and gets reset if another byte is written before it expires. When the timer expires, an internal write cycle is triggered and additional writes before it completes. It's possible the device gets "unhappy" if /WE goes low and stays low for the entire duration of the timer. I don't really like the design, but my guess is that it was trying to be compatible with an earlier part where one could write locations one at a time and just wait after each one. \$\endgroup\$ – supercat Mar 27 '13 at 16:38
  • \$\begingroup\$ @MatthewR.: BTW, if the chips are equipment pulls as opposed to new parts, it's possible that the "software protection" feature has previously been enabled. If it has, you'll need to wire up all your address wires in order to disable it. \$\endgroup\$ – supercat Mar 27 '13 at 16:41
  • \$\begingroup\$ @supercat: Thanks for the info. The chips are new, and I actually have two from two different manufacturers. All behave the same. \$\endgroup\$ – Matthew R. Mar 27 '13 at 20:46
  • \$\begingroup\$ @MatthewR.: I'd suggest you test what happens if you don't leave the /WE line asserted for more than a couple microseconds or so at a time. That might help things. \$\endgroup\$ – supercat Mar 27 '13 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.