Steuerung von 23K256 SPI RAM mit Arduino

Ich versuche, mit einem Arduino Mega 2560 eine Schnittstelle zu einem 23K256-SPI-RAM-IC herzustellen. Ich kann die Standard-SPI-Pins nicht verwenden, da ich ein Ethernet-Schild verwende und es nicht gut spielt, wenn SS hoch eingestellt ist.

Also versuche ich stattdessen, es zu bit-bangen. Ich habe ein paar eigene Methoden ausprobiert und schließlich den Code aus dem Link in der Beschreibung dieses Videos ausgeliehen , aber es scheint überhaupt nicht zu funktionieren.

// hold pin is wired directly to VCC (3.3V)
int RAMClockPin = 14;
int RAMInPin = 15;
int RAMOutPin = 11; 
int RAMSelectPin = 12;

// These are hard-wired in the chip
int RAM_READ_COMMAND = 3;    // 00000011
int RAM_WRITE_COMMAND = 2; // 00000010 

//================================================

// Send a byte into the chip's input, bit by bit
void RAMRawWrite(byte b) {

  // Cycle through the 8 bits in the byte
  for (int j = 0; j < 8; j++) {

     // Send MSB (Most Significant Bit) to chip
     if ((b & 0x80) == 0x80) digitalWrite(RAMInPin, HIGH);
       else digitalWrite(RAMInPin, LOW);
     // Send a clock pulse
     digitalWrite(RAMClockPin, HIGH); 
     digitalWrite(RAMClockPin, LOW); 
     // Shift the rest of the bits, one to the left
     b = b << 1;

   }  

}

//================================================

// The whole procedure of sending a data byte
void writeToRAM(unsigned int wAddr, byte wValue) {

  // Pointer to a byte
  byte *bp;

  // Point to higher byte of address (wAddr is 2 bytes long)
  bp = (byte *)&wAddr + 1;
  // Start session
  digitalWrite(RAMSelectPin, LOW);
  // Send the "write" command
  RAMRawWrite(RAM_WRITE_COMMAND);
  // Send the address, one byte at a time
  RAMRawWrite(*bp); // Higher byte
  bp--;
  RAMRawWrite(*bp); // Lower byte
  // Send the data byte
  RAMRawWrite(wValue);
  // Close session
  digitalWrite(RAMSelectPin, HIGH);   

}

//================================================

// The whole procedure of reading a data byte
byte readFromRAM(unsigned int rAddr) {

  byte b, currBit;
  byte *bp;

  // Point to higher byte of address
  bp = (byte *)&rAddr + 1;
  // Start session
  digitalWrite(RAMSelectPin, LOW);
  // Send the "read" command
  RAMRawWrite(RAM_READ_COMMAND);
  // Send address
  RAMRawWrite(*bp); // Higher byte
  bp--;
  RAMRawWrite(*bp); // Lower byte

  // Get bits, MSB-first
  b = 0;
  for (byte currBit = 0x80; currBit > 0; currBit = currBit >> 1) {

     // Clock signal start
     digitalWrite(RAMClockPin, HIGH); 
     // Get one bit of data, put it in the appropriate place 
     if (digitalRead(RAMOutPin) == HIGH) b += currBit;
     // Clock signal end
     digitalWrite(RAMClockPin, LOW); 

  }  

  // End session and return result
  digitalWrite(RAMSelectPin, HIGH);   
  return b;

}

void setup() {
  Serial.begin(9600);
  pinMode(RAMClockPin, OUTPUT);
  pinMode(RAMInPin, OUTPUT);
  pinMode(RAMOutPin, INPUT);
  pinMode(RAMSelectPin, OUTPUT);  
  digitalWrite(RAMSelectPin, HIGH);

  Serial.println("Writing 0xA3 to 16");
  writeToRAM(16, 0xA3);
  Serial.println("Reading back...");
  byte value = readFromRAM(16);
  Serial.println(value, HEX);
}

void loop() {}

Das Ergebnis des Lesens ist 0x00jedes Mal. Ich habe meine PIN-Nummern doppelt und dreifach überprüft und versucht, SI/ umzukehren SO, aber es funktioniert immer noch nicht. Leider habe ich kein Scope um die Daten zu testen.

Irgendwelche Ideen?

Welche Versorgungsspannung hat dein Mikrocontroller?
Nicht ganz sicher. Ich betreibe es über USB.
Nun, die Spezifikationen für Ihr Board sagen, dass es 5 V sind, aber der Kommentar am Anfang Ihres Codes sagt 3,3 V. Also welches ist es? Und wird der Speicherchip mit der gleichen Spannung versorgt?
Auf der Platine befinden sich zwei Stromanschlüsse - 3,3 V und 5 V. Ich denke, es hat einen Onboard-Regler. Der Speicher-IC wird vom 3,3-V-Pin auf der Platine mit Strom versorgt. Siehe unten links in diesem Bild: arduino.cc/en/uploads/Main/ArduinoMega2560_R3_Front.jpg

Antworten (1)

Ihr Problem ist wahrscheinlich eine Nichtübereinstimmung der Logikebene. Da Ihr RAM-IC mit 3,3 V versorgt wird, kann sein HIGH-Ausgangspegel am SO-Pin nicht größer als 3,3 V sein. Ihr Mikrocontroller scheint jedoch 5 V zu verwenden (siehe Schaltpläne ) . Jetzt habe ich keine AVR-Datenblätter konsultiert, aber die meisten CMOS-Chips erkennen einen HIGH-Pegel, wenn die Spannung an ihren Eingängen größer als 0,7 Vcc ist. Diese Schwelle beträgt 0,7 * 5 V = 3,5 V, daher hat der Mikrocontroller jedes Recht, 3,3 V nicht als HIGH zu erkennen. Dies kann gut erklären, warum Sie alle Nullen aus Ihrem RAM lesen.

Beachten Sie, dass der maximale Eingangs- HIGH-Pegel, den Ihr RAM toleriert, Vcc + 0,3 V (Tabelle 1.1) beträgt, was in Ihrem Fall 3,6 V entspricht. Das ist viel kleiner als die 5 V, die Ihre MCU ausgibt, sodass Sie Ihren RAM möglicherweise bereits gekocht haben. Der Unterschied reicht sicherlich aus, um Schutzdioden in den leitenden Zustand zu bringen. Einige 3,3-V-ICs haben 5-V-tolerante Eingänge, dieser nicht.

Ihre Optionen sind:

  • Betreiben Sie Ihre MCU mit 3,3 V. Dies ist oft am besten, wenn Ihre MCU diese Spannung unterstützt (ich denke, das tut sie), da dadurch die Notwendigkeit einer Pegelumsetzung vollständig vermieden wird. Leider scheint dies innerhalb der Grenzen Ihrer Plattform kaum möglich zu sein.

  • Erhöhen Sie Vcc Ihres RAM (Datenblatt sagt, dass es bis zu 3,6 V tolerieren kann). Dies wird jedoch unzuverlässig sein, da der Schwellenwert nur geringfügig überschritten wird, sodass jegliche Spannungsschwankungen (und sogar interne Schwankungen zwischen einzelnen Chips) durchaus zu Problemen führen können. Dies löst auch nicht die Fehlanpassung des Eingangspegels, sodass die Hälfte des Problems bestehen bleibt.

  • Führen Sie eine logische Ebenenübersetzung in beide Richtungen durch. Es gibt viele Lösungen für dieses Problem, Sie sollten das Internet (einschließlich dieser Website) durchsuchen, um sich ein Bild zu machen. Kurz gesagt, es ist einfacher, die Spannung von 5 V auf 3,3 V zu senken (ein Teiler reicht aus, vielleicht mit einer Diode), als umgekehrt (Sie müssen einen FET oder einen IC als Puffer verwenden). Diese Appnote zeigt einige Schaltungen, ebenso wie diese Seite . Siehe auch dieses Produkt von Sparkfun für eine ähnliche Idee. HEF4050BT ist ein Puffer-IC mit absoluten Eingangsschwellen (HIGH ist 3 V) und kann bis zu 15 V an Eingängen tolerieren. Ich bin mir sicher, dass es noch mehr Möglichkeiten gibt, aber ich persönlich glaube, dass es am besten ist, Ihre Mikrocontroller mit 3,3 V zu versorgen und sich den Ärger zu ersparen. Viele nützliche ICs sind heutzutage nicht 5V-kompatibel (oder tolerant).

Ugh, ich habe nie daran gedacht, die Logikpegel zu überprüfen. Ich hoffe wirklich, dass ich den IC nicht geraucht habe. Ich habe mehrere Ersatzteile, also muss ich den Rest testen. Ich kann sehen, wie die LLC auf Sparkfun die Übersetzung von 3,3 V auf 5 V durchführt, aber ich kann die Übersetzung von 5 V auf 3,3 V nicht ganz herausfinden. Wird ein Potentialteiler verwendet, um den Logikpegel auf 3,3 V zu senken?