Controlando 23K256 SPI RAM con Arduino

2

Estoy tratando de interactuar con un 23K256 SPI RAM IC utilizando un Arduino Mega 2560 . No puedo usar los pines SPI estándar, ya que estoy usando un escudo de Ethernet y no funciona bien cuando el SS está alto.

Entonces, en cambio, estoy tratando de golpearlo. He intentado algunos métodos propios y, finalmente, tomé prestado el código del enlace en descripción de este video , pero no parece funcionar en absoluto.

// 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() {}

El resultado de la lectura es 0x00 cada vez. He comprobado el doble y el triple de mis números de pin y he intentado revertir SI / SO , pero aún no funciona. Desafortunadamente no tengo un alcance para probar los datos.

¿Alguna idea?

    
pregunta Polynomial

1 respuesta

2

Su problema es probable que no coincida el nivel lógico. Debido a que su IC RAM se alimenta con 3.3V, su nivel de salida ALTO en el pin SO no puede ser mayor que 3.3V. Sin embargo, su microcontrolador parece usar 5V (mirando el schematics ). Ahora no he consultado hojas de datos AVR, pero la mayoría de los chips CMOS reconocen un nivel ALTO cuando el voltaje en sus entradas es mayor que 0.7 Vcc. Este umbral es 0.7 * 5V = 3.5V, por lo que el microcontrolador tiene todo el derecho de no reconocer 3.3V como ALTO. Esto bien puede explicar por qué estás leyendo todos los ceros de tu RAM.

Tenga en cuenta que el nivel máximo de entrada ALTO que su RAM tolera es Vcc + 0.3V (tabla 1.1), que en su caso es igual a 3.6V. Eso es mucho más pequeño que la salida de 5 V de su MCU, por lo que es posible que ya haya cocinado su RAM. La diferencia es ciertamente suficiente para desviar los diodos de protección hacia la conducción. Algunos circuitos integrados de 3.3 V tienen entradas tolerantes de 5 V, pero esta no.

Sus opciones son:

  • Ejecute su MCU a 3.3V. Esto suele ser mejor si su MCU soporta ese voltaje (creo que sí), ya que evita la necesidad de una traducción de nivel por completo. Desafortunadamente, esto no parece posible dentro de los límites de su plataforma.

  • Aumente el Vcc de su RAM (la hoja de datos dice que puede tolerar hasta 3.6V). Sin embargo, esto no será confiable, ya que el umbral solo se supera ligeramente, por lo que cualquier variación de voltaje (e incluso las variaciones internas entre chips individuales) puede generar problemas. Esto tampoco resuelve la falta de coincidencia del nivel de entrada, por lo que la mitad del problema permanece.

  • Realice la traducción a nivel lógico en ambas direcciones. Existen muchas soluciones a este problema, debe buscar en la web (incluido este sitio web) para obtener la imagen. En resumen, es más fácil reducir el voltaje de 5V a 3.3V (un divisor es suficiente, quizás con un diodo) que hacer el inverso (deberá usar un FET o un IC como búfer). Este appnote muestra algunos circuitos, al igual que esta página . Vea también este producto de Sparkfun para una idea similar. HEF4050BT es un IC de búfer con umbrales de entrada absolutos (ALTO es de 3 V) y puede tolerar hasta 15 V en las entradas. Estoy seguro de que existen más posibilidades, pero personalmente creo que es mejor alimentar a sus microcontroladores con 3.3 V y evitar los problemas. Muchos circuitos integrados útiles no son compatibles con 5V (o tolerantes) en estos días.

respondido por el Thorn

Lea otras preguntas en las etiquetas