28C64 EEPROM-Programmierung mit Arduino

7

Ich arbeite an einem Z80-Computer und musste Daten in ein EEPROM schreiben. Ich verwende den Xicor 28C64AP-25-Chip ( Datenblatt ). Ich habe ein Programm für das Arduino Uno geschrieben, das Daten an die ersten 4 Adressen schreibt und diese dann zurückliest. Da ich nur die ersten drei Adresspins verwende, ist der Rest niedrig gebunden. Hier ist mein Code, sorry, wenn er zu unübersichtlich erscheint:

#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 dies soll delaynur sicherstellen, dass ich nicht zu schnell für das EEPROM bin. Ich kann über einige LEDs erkennen, dass der Arduino die richtigen Daten an die E / A-Pins des EEPROM ausgibt, aber wenn ich die Daten zurücklese, erhalte ich nur 0xFF. Hier ist der serielle Ausgang.

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

Ich habe eine frühere Version des obigen Programms mit einem statischen RAM-Chip getestet und alles funktioniert hervorragend. Mit dem EEPROM funktioniert es einfach nicht.

Jede Hilfe wäre sehr dankbar.

Matthew R.
quelle
Eine Sache, die fehlt, befindet sich auf Seite 7 des Datenblattes. Dort heißt es, dass Sie eine Folge von Codes schreiben müssen, um den Schreibschutz zu deaktivieren.

Antworten:

4

Das Gerät verfügt über 13 Adresspins, die eine binäre Adresse von 0x0000 bis 0x1FFF angeben sollen. Sie haben nicht angegeben, dass Sie etwas mit ihnen tun?

Außerdem würde ich vorschlagen, dass Sie eine writebyteProzedur schreiben , die alle Adress- und Datenleitungen auf Ausgabe setzt und die richtigen Werte auf sie legt, sicherstellt, dass WE und OE deaktiviert sind, CE aktiviert, WE aktiviert und freigegeben und CE freigibt, und eine readbyteProzedur, die Setzt alle Adressdrähte auf Ausgang und legt die richtigen Werte fest, setzt alle Datenkabel auf Eingang, aktiviert CE und OE, tastet alle Datenkabel ab und gibt CE und OE frei. Dadurch wird der Rest Ihres Codes viel besser lesbar.

Superkatze
quelle
Danke für die Antwort, @supercat. Ich habe die Top 10 Adressbits niedrig gebunden und verwende vorerst nur die ersten 3. Ich habe meine Frage bearbeitet. Ich verstehe die Vorteile der Aufteilung des Codes in Unterprogramme und werde dies wahrscheinlich tun, aber im Moment versuche ich nur, das Byte-Schreiben zum Laufen zu bringen.
Matthew R.
1

Das Datenblatt auf Seite 12 zeigt ein Zeitdiagramm und die Zugriffszeit für die Chipaktivierung kann bis zu 250 ns betragen. Wenn Sie einen AVR mit einer Uhr> = 4 MHz verwenden, sind Sie möglicherweise unter dieser Zeit und benötigen einige kleine Verzögerungen in Ihrem Lesecode. Versuchen Sie zunächst vielleicht sogar lange Verzögerungen, wie Sie es mit dem Schreibcode getan haben, bis Sie wissen, dass es funktioniert.

Das gleiche Diagramm zeigt, wie CE für einen Lesezyklus aktiviert wird, gefolgt von OE. Ich würde empfehlen, dieselbe Reihenfolge einzuhalten und auch Ihre Schreibsequenz zu ändern, um dem Diagramm auf der folgenden Seite zu folgen.

PeterJ
quelle
Ich habe zwischen jedem Steuerstiftwechsel 500 ms Verzögerung hinzugefügt und sichergestellt, dass die Reihenfolge mit dem Datenblatt übereinstimmt, aber immer noch kein Glück. Benötigen EEPROMs ein genaues Timing, was bedeutet, dass ich jetzt den Chip verlangsamen könnte? Vielen Dank.
Matthew R.
@MatthewR.: Die Timings für dieses spezielle EEPROM sind nicht überkritisch, aber es hat einen Timer, der beim Schreiben des ersten Bytes startet und zurückgesetzt wird, wenn ein anderes Byte geschrieben wird, bevor es abläuft. Wenn der Timer abläuft, wird ein interner Schreibzyklus ausgelöst und zusätzliche Schreibvorgänge ausgeführt, bevor er abgeschlossen ist. Es ist möglich, dass das Gerät "unglücklich" wird, wenn / WE niedrig wird und für die gesamte Dauer des Timers niedrig bleibt. Ich mag das Design nicht wirklich, aber ich vermute, dass es versucht hat, mit einem früheren Teil kompatibel zu sein, in dem man Orte einzeln schreiben und einfach nach jedem warten konnte.
Supercat
@MatthewR.: Übrigens, wenn es sich bei den Chips im Gegensatz zu Neuteilen um Gerätezüge handelt, ist es möglich, dass die Funktion "Softwareschutz" zuvor aktiviert wurde. Wenn dies der Fall ist, müssen Sie alle Adresskabel verkabeln, um es zu deaktivieren.
Supercat
@ Supercat: Danke für die Info. Die Chips sind neu und ich habe tatsächlich zwei von zwei verschiedenen Herstellern. Alle verhalten sich gleich.
Matthew R.
@MatthewR.: Ich würde vorschlagen, dass Sie testen, was passiert, wenn Sie die / WE-Leitung nicht länger als ein paar Mikrosekunden oder so gleichzeitig belassen. Das könnte helfen.
Supercat