Cómo escribir en 93LC46B EEPROM desde un Arduino usando SPI

4

Tengo una pregunta con respecto a eeproms y un Arduino (estoy usando Arduino Uno). Tengo el siguiente eeprom: 93LC46B . De la hoja de datos, entiendo que para escribir los enteros 1 y 2 en la primera dirección, necesito enviar los siguientes bits:

  • 1 : bit de inicio
  • 01 : escribir código de operación
  • 000000 : primera dirección
  • 00110001 : 1
  • 00110010 : 2

El resultado es 1010000000011000100110010

Tengo el siguiente código pero parece que no puedo encontrar la forma de enviar los bits, ¿alguien puede ayudarme?

#include "SPI.h"
int ss=10;

void setup()
{
  pinMode(ss, OUTPUT);
  digitalWrite(ss, LOW);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);

  digitalWrite(ss, HIGH);
  //what to send?
  digitalWrite(ss, LOW);
}

Así que actualicé mi código pero aún no puedo obtener el resultado deseado. Este es el código:

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO 
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define READ  0x80
#define WRITE 0x40

byte eeprom_output_data;
byte clr;

void setup()
{
  Serial.begin(9600);

  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK, OUTPUT);
  pinMode(SLAVESELECT, OUTPUT);
  digitalWrite(SLAVESELECT, LOW); //disable device

  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10);

  digitalWrite(SLAVESELECT, HIGH);
  digitalWrite(DATAOUT, HIGH);
  digitalWrite(SPICLOCK, HIGH);
  delay(1);
  digitalWrite(SPICLOCK, LOW);

  spi_transfer(WRITE); //01000000
  spi_transfer(0x10);
  spi_transfer(0x11);

  digitalWrite(SLAVESELECT,LOW); //release chip
  delay(3000);

  eeprom_output_data = read_eeprom();
  Serial.print(eeprom_output_data,DEC);
  Serial.print('\n');
  delay(500); //pause for readability
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

byte read_eeprom()
{
  //READ EEPROM
  int data;

  digitalWrite(SLAVESELECT, HIGH);
  digitalWrite(DATAOUT, HIGH);
  digitalWrite(SPICLOCK, HIGH);
  delay(1);
  digitalWrite(SPICLOCK, LOW);

  spi_transfer(READ); //transmit read opcode
  data = spi_transfer(0xFF); //get data byte
  digitalWrite(SLAVESELECT, LOW); //release chip, signal end transfer
  return data;
}

void loop()
{
}
    
pregunta Jeroen

1 respuesta

5

Para escribir datos SPI utilizando la biblioteca uno utiliza la función transfer () de la biblioteca SPI: toma un argumento de byte y, en realidad, lo envía por el bus SPI. Puede especificar más argumentos, es decir, qué hacer con el pin SS, pero esto no parece preocuparle.

El ejemplo de Arduino SPI EEPROM también puede ser útil.

Si necesita enviar datos que no sean de 8 bytes, sería extremadamente conveniente si el tamaño de los datos (en bits) fuera un múltiplo de 8. En este caso, los datos se envían en 8 bits (o trozos de un byte. La forma más sencilla de hacerlo es tratar sus datos como una matriz de bytes:

byte data[] = {0x00, 0x00, 0x00, 0x00};  // this is 24 bits (8bits/byte * 4 bytes)

// Transfer 24 bits of data
for (int i=0; i<4; i++) {
   transfer(data[i]);   // Send 8 bits
}
  

Pregunta: Estoy muy confundido por este bit " 8 * 4 = 24 " arriba y abajo. Esto no tiene sentido para mí. Además, ¿no es SPI.transfer , no solo transfer ?

Enviar datos que no sean múltiplos de 8 bits es un poco complicado con SPI en Arduino / AVR. Pero parece que, de hecho, su EEPROM requiere datos de 25 bits para escribir. Como Arduino SPI solo permite que los datos se envíen en fragmentos de 8 bits, la solución es generar la condición de inicio antes de enviar los datos SPI utilizando la biblioteca SPI:

  // This is our setup
  pinMode(ss, OUTPUT);
  digitalWrite(ss, LOW);

  // Generate the start condition
  digitalWrite(ss, HIGH);
  digitalWrite(SPI_MOSI, HIGH);
  digitalWrite(SPI_CLK, HIGH);
  delay(1); // pause
  digitalWrite(SPI_CLK, LOW);
  // done with the start condition

  // Normal SPI write
  // no need to twiddle SS bits since SS is already high
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  ... // send stuff here
  digitalWrite(ss, LOW);

Esta técnica se llama bit banging : aumento y disminución de las salidas digitales en el software de acuerdo con algunas especificaciones de protocolo en Para interactuar con algún periférico o comunicarse con otro chip. De hecho, usted mismo podría golpear todos los datos utilizando digitalWrite() y omitir la biblioteca SPI por completo. No es realmente difícil, y ya lo estamos haciendo para generar la condición de inicio. Cómo se vería esto en cada bit:

digitalWrite(SPI_CLOCK, LOW);
digitalWrite(SPI_MOSI, yourBitValueHere);
digitalWrite(SPI_CLOCK, HIGH);
delay(1);

SPI_MOSI sería el pin conectado a tu EEPROM DI pin, o el pin SPI DATA en tu Arduino. SPI_CLOCK sería el pin conectado al pin CLK de su EEPROM. Si no está utilizando la biblioteca SPI, puede conectar cualquier pin de salida digital a la EEPROM. La biblioteca de spi está limitada al uso de los pines SPI de Arduino, creo.

    
respondido por el angelatlarge

Lea otras preguntas en las etiquetas