Autor Tema: EEPROM Cloner con Arduino  (Leído 156 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1093
EEPROM Cloner con Arduino
« en: 29 de Noviembre de 2019, 22:42:12 »
Que tal amigos del foro.

En esta entrega quisiera compartir la versión de un proyecto que ya había compartido. Se trata del clonador/copiador de memorias seriales EEPROM con interface I2C, de la familia 24XXXX.
En esta versión usaré un Arduino NANO usando solamente un solo bus I2C, habilitando y deshabilitando la alimentación de la memoria fuente y la memoria destino.

Para el presente proyecto necesitaremos:

1) Arduino Nano
 

* Arduino_nano.JPG
(51.57 kB, 502x503 - visto 55 veces)


2) LCD con interface I2C
 

* LCD_I2C_front.JPG
(28.7 kB, 510x413 - visto 53 veces)

 

* LCD_I2C_back.JPG
(39.95 kB, 506x408 - visto 53 veces)


3) Breadboard y alambre de conexión.

4) Dos memorias I2C:
    a)24LC00
    b)24LC01
    c)24LC02
    d)24LC04
    e)24LC08
    f)24LC16
    g)24LC32
    h)24LC64
    i)24LC128
    j)24LC256
    k)24LC512
    l)24LC1026
    m)24LC1025
    n)AT24CM01
    o)AT24CM02


   

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1093
Re:EEPROM Cloner con Arduino
« Respuesta #1 en: 29 de Noviembre de 2019, 22:53:54 »
Y ahora el esquemático:

 

* EEPROM cloner arduino.JPG
(151.89 kB, 892x596 - visto 58 veces)


Y por supuesto lo más importante el scketch para el arduino:

Código: [Seleccionar]
#include <Wire.h>               // Includes the Wire library for I2C communication
#include <LiquidCrystal_I2C.h>  // Includes the LiquidCrystal_I2C library

#define lcdAddress 0x3f         // LCD I2C Address
#define  CTL      0X50          //Byte de control para memorias 24C00 hasta la 24C512
#define  CTLM1    0x51          //Byte de control para memorias 24LC1024, 24LC1026 y AT24CM01
#define  CTLM2    0X52          //Byte de control para memorias AT24CM02
#define  CTL1025  0x54          //Byte de control para memoria 24LC1025
#define VDD_SRC 4               // Define digital port 4 as VDD for source memory
#define VDD_TAR 5               // Define digital port 5 as VDD for target memory
#define START_SW  3             // Define digital port 3 as Start switch
#define SEL_SW  2               // Define digital port 2 as Selector switch

#define CE  6       //Chip Enable for Timer
#define RST 7       //Reset for Timer

LiquidCrystal_I2C lcd( lcdAddress );   // Create instance of LiquidCrystal_I2C and set the LCD I2C address
char buff[16];
byte ACK,model_flag;
unsigned int model,model0;
long num;

// Definición de funciones
void NO_MEM_SRC();    //Función para mostrar que no se encontró la memoria fuente
void NO_MEM_TARG();   //Función para mostrar que no se encontró la memoria destino
void enable_source(); //Función para habilitar la memoria fuente y deshabilitar la memoria destino
void enable_target(); //Función para habilitar la memoria destino y deshabilitar la memoria fuente
void i2cmemdtc();     //Función para detectar el tipo de memoria. Desde 24C00 hasta la 24CM02
void done_msg();      //Función para mostrar en la LCD el mensaje de que la copia se realizó correctamente
void copy_mem_24C00();  //Función para realizar la copia de la memoria 24C00
void copy_mem();      //Función para realizar la copia de las memorias 24CXXXX

void setup()
{
  pinMode(CE,OUTPUT);
  pinMode(RST, OUTPUT);
 
  pinMode(VDD_SRC, OUTPUT);
  pinMode(VDD_TAR, OUTPUT);
  pinMode(START_SW, INPUT_PULLUP);
  pinMode(SEL_SW, INPUT_PULLUP);
  digitalWrite(VDD_SRC, LOW);
  digitalWrite(VDD_TAR, LOW);

  digitalWrite(CE, LOW);
  digitalWrite(RST,LOW);
  digitalWrite(RST,HIGH);

  Serial.begin(9600);   //Set serial port @9600 bps for debugging
 
  lcd.begin(16,2);              // initialize the lcd as a 16 characters by 2 row display
  Wire.setClock(400000);        // Set I2C clock at 400KHz
  lcd.setBacklight(HIGH);       // Turn on the LCD's backlight
  lcd.home ();                  // set the cursor to the home position (first row, first column)
  lcd.print("  24XXX SERIES");//
  //sprintf(buff, "  24XXX SERIES");
  //lcd.print(buff);
  lcd.setCursor ( 0, 1 );       // set cursor to first character of line 2
  lcd.print(" CLONER VER 1.0");
  delay(1500);
  lcd.clear();
  lcd.print("  DESIGNED BY:");
  lcd.setCursor(0,1);
  lcd.print("   MIGUEL MEZA");
  delay(1500);
  lcd.clear();
  lcd.print("  ARDUINO NANO");
  lcd.setCursor(0,1);
  lcd.print("ARDUINO V: 1.8.4");
}

void loop()
{
  model_flag = 0;
  while (model_flag==0)
  {
    ACK = 2;      //Set NACK value received on transmit of address
    while (ACK==2)
    {
      while (ACK==2)
      {
        delay(1500);
        lcd.clear();
        lcd.print(" INSERT MEMORIES");
        lcd.setCursor(0,1);
        lcd.print("   PRESS START");
        while(digitalRead(START_SW));
        //enable_source();              //Enable source memory
        digitalWrite(VDD_SRC,HIGH);
        delayMicroseconds(100);
        Wire.beginTransmission(CTL);  //Send a start bit and Send CTL Byte to the source memory
        ACK = Wire.endTransmission(); //Send a stop bit and wait the ACK from the source memory
        if (ACK==2)     //Is a NACK bit?
          NO_MEM_SRC(); //Yes, then show there is no source memory
      }
      enable_target();  //No, it is an ACK bit, then enable target memory
      Wire.beginTransmission(CTL);  //Send a start bit and Send CTL Byte to the target memory
      ACK = Wire.endTransmission(); //Send a stop bit and wait the ACK from the target memory
      if (ACK==2)       //Is a NACK bit?
        NO_MEM_TARG();  //Yes, then show there is no target memory
    }

    //digitalWrite(VDD_SRC,LOW);
    //digitalWrite(VDD_TAR,LOW);
    //lcd.clear();
    //lcd.print("Memories OK");
    enable_source();
    i2cmemdtc();

    //digitalWrite(VDD_SRC, LOW);   //Disable source memory for debugging
   
    model0=model;
    lcd.clear();
    lcd.print("SRC MEM:24C");
    if (model<10)
    {
      sprintf(buff,"%02u",model);
      lcd.print(buff);
    }
    else
    {
      sprintf(buff,"%u",model);
      lcd.print(buff);
    }
    enable_target();
    i2cmemdtc();
    lcd.setCursor(0,1);
    lcd.print("TARG MEM:24C");
    if (model<10)
    {
      sprintf(buff,"%02u",model);
      lcd.print(buff);
    }
    else
    {
      sprintf(buff,"%u",model);
      lcd.print(buff);
    }
               
    delay(1500);   
    if (model==model0)
    {
      if ((model==32) && (model0==32) && (digitalRead(SEL_SW)==1))
      {
          digitalWrite(VDD_SRC, LOW);
          digitalWrite(VDD_TAR, LOW);
          lcd.clear();
          lcd.print("CAN'T COPY");
          lcd.setCursor(0,1);
          lcd.print("CHANGE COPY MODE");
      }
      else
          model_flag = 1;
     } 
     else
     {
        lcd.clear();
        lcd.print("UNMATCH MEMORIES");
        lcd.setCursor(0,1);
        lcd.print("REPLACE MEMORIES");
        digitalWrite(VDD_SRC, LOW);
        digitalWrite(VDD_TAR, LOW);
       
      }
   }
         lcd.clear();
         lcd.print("MATCHED MEMORIES");
         lcd.setCursor(0,1);
         lcd.print("COPYING...");

         digitalWrite(RST, LOW);
         digitalWrite(RST, HIGH);
         digitalWrite(CE, HIGH);
         
         if (model==0)
            copy_mem_24C00();
         else
            copy_mem();

         digitalWrite(CE, LOW);
                     
         done_msg();
}

void  NO_MEM_SRC()
{
   digitalWrite(VDD_SRC,LOW);         // Turn off source memory
   digitalWrite(VDD_TAR,LOW);       //Turn off target memory
   lcd.clear();                     // Clear LCD display
   lcd.print("NO SOURCE MEMORY");  // Show "NO SOURCE MEMORY" in LCD
   lcd.setCursor(4,1);
   lcd.print("IN SOCKET");
   return;
}

void NO_MEM_TARG()
{
   digitalWrite(VDD_TAR,LOW); // Turn off target memory
   digitalWrite(VDD_SRC,LOW); //Turn off source memory
   lcd.clear();
   lcd.print("NO TARGET MEMORY");
   lcd.setCursor(4,1);
   lcd.print("IN SOCKET");
   return;
}
 
void enable_source()
{
   digitalWrite(VDD_TAR,LOW);   //Turn off Target memory
   delay(1);
   digitalWrite(VDD_SRC,HIGH);  //Turn on Source Memory
   delayMicroseconds(100);
   return;
}

void  enable_target()
{
   digitalWrite(VDD_SRC,LOW);   //Turn off Source memory
   delay(1);
   digitalWrite(VDD_TAR,HIGH);  //Turn on Target Memory
   delayMicroseconds(100);
   return;
}

void  done_msg()
{
   lcd.clear();
   lcd.print("MEMORY COPIED");
   lcd.setCursor(0,1);
   lcd.print("SUCCESSFUL COPY");
   digitalWrite(VDD_SRC, LOW);
   digitalWrite(VDD_TAR, LOW);
   return;   
}

void i2cmemdtc()
{
byte backup,ctl_byte,temp,temp0,new_value;
byte    OK_flag;
unsigned long top_num;
   if (digitalRead(SEL_SW)==0)      //¿Se ha seleccionado el modo smart?
   {
      Wire.beginTransmission(CTLM2);  // Sí, entonces envía el byte de control de la memoria de 2Mbits
      ACK = Wire.endTransmission();   // Envía el bit de paro y revisa si llegó un ACK
     
      if (ACK==0)                //¿Se recibió un bit de ACK?
      {       
         model = 2048;           //Sí, entonces asigna el modelo de memoria de 2Mb
         num = 262144;           //Asigna la capacidad máxima
         return;                 //Termina subrutina de detección
      }
      Wire.beginTransmission(CTLM1);  // Sí, entonces envía el byte de control de la memoria de 1Mbits
      ACK = Wire.endTransmission();   //Envía el bit de paro y revisa si llegó un ACK
     
      if (ACK==0)                  //¿Se recibió un bit de ACK?
      {
         model = 1024;           //Sí, entonces asigna modelo de memoria de 1Mb
         num = 131072;           //Asigna la capacidad máxima
         return;                 //Termina subrutina
      }
      Wire.beginTransmission(CTL1025);  // Sí, entonces envía el byte de control de la memoria de 1Mbits
      ACK = Wire.endTransmission();     //Envia el bit de paro y revisa si llegó un ACK

      if (ACK==0)                //¿Se recibió un bit de ACK?
      {
         model = 1025;           //Sí, entonces asigna modelo de memoria de 1Mb
         num = 131072;           //Asigna la capacidad máxima
         return;                 //Termina subrutina
      }
   }
   num = 16;                     //Inicializa valor de desborde para la memoria 24C00
   model = 0;                    //Inicializa el modelo de memoria en 00, indicando memoria 24C00
   top_num = 2048;               //Inicializa el valor máximo de desborde para memorias standard
   if (digitalRead(SEL_SW)==0)      //¿Se ha selleccionado el modo smart?
   {
      num = 4096;                //Sí, entonces inicializa el valor de desborde para la memoria 24C32
      model = 32;                //Inicializa modelo de memora 24C32
      top_num = 65536;           //Inicializa valor máximo de desborde para memorias de modo smart
   }
   while (num<=top_num)          //¿Ya se ha alcanzado el valor máximo de desborde?
   {
      Wire.beginTransmission(CTL);  //Envía el byte de control
      if (digitalRead(SEL_SW)==0)   //¿Se ha seleccionado modo smart?
         Wire.write(0);           //Sí, entonces envía la parte alta de la dirección 0x0000
      Wire.write(0);              //Envía la dirección a leer 0x00
      Wire.endTransmission();
      Wire.requestFrom(CTL,1);    // Solicita la lectura de un byte
      if(Wire.available())         //Existe un dato disponible?
        backup = Wire.read();      //Sí, entonces realiza lectura del byte en la dirección 0x00 (0x0000 smart) sin bit de ACK
     
      num--;                     //Decrementa en uno el valor de desborde
      OK_flag=0;                 //Limpia la bandera de OK
      ctl_byte = num>>8;         //Prepara el byte de control de escritura

      //sprintf(buff,"%X",top_num);
      //Serial.print(buff);
      //Serial.println(num, HEX);
      //Serial.print("     ");
      //Serial.println(ctl_byte, HEX);
      //ctl_byte = ctl_byte<<1;
      ctl_byte = ctl_byte | CTL;

      //Serial.println(ctl_byte, HEX);
     
      if (digitalRead(SEL_SW)==0)   //¿se ha seleccionado el modo smart?
         ctl_byte=CTL;           //Sí, entonces asigna el valor por default (0XA0) del byte de control
      Wire.beginTransmission(ctl_byte);       //Envía el byte de control de escritura
      if (digitalRead(SEL_SW)==0)   //¿Se ha seleccionado el modo smart?
         Wire.write((int)(num>>8));      //sí, entonces envia el la parte alta de la dirección de desborde
      Wire.write((int)(num & 0xFF));            //Envía la dirección de desborde
      Wire.endTransmission();
      Wire.requestFrom(ctl_byte,2);       //Envía el byte de control de lectura
      if (Wire.available())
        temp = Wire.read();         //Recibe dos datos consecutivos
      if (Wire.available())
        temp0 = Wire.read();
     
      if (temp0 == backup);      //¿El segundo dato es igual al valor contenido en la dirección 0x00 (0x0000 para modo smart)?
      {
         new_value = backup + 1; //Sí, entonces incrementa el valor contenido en la dirección 0x00 (0x0000 para modo smart) a la variable new_value
         Wire.beginTransmission(CTL);         //Envía el byte de control de escritura (0xA0)
         if (digitalRead(SEL_SW)==0)   //¿Se ha seleccionado el modo smart?
            Wire.write(0);        //Sí, entonces escribe la parte alta de la dirección 0x0000
         Wire.write(0);           //Envía la dirección a escribir 0x00 (parte baja de la dirección en modo smart)
         Wire.write(new_value);   //Envía el valor de la variable new_value
         Wire.endTransmission();
         delay(10);           //Espera 10ms para que se escriba el dato
 
         Wire.beginTransmission(ctl_byte);    //Envía el byte de control de escritura
         if (digitalRead(SEL_SW)==0)   //¿Se ha seleccionado el modo smart?
            Wire.write((int)(num>>8));   //Sí, entonces envía la parte alta de la dirección de desborde
         Wire.write((int)(num & 0xFF));         //Envía la dirección de desborde
         Wire.endTransmission();
         Wire.requestFrom(ctl_byte,2);    //Envía el byte de control de lectura
         if (Wire.available())
          temp = Wire.read();      //recibe dos datos consecutivos
         if (Wire.available())
          temp0 = Wire.read();   
         
         if (temp0==new_value)   //¿Son iguales el segundo dato y el valor de New_value?
            OK_flag = 1;         //Sí, entonces levanta la bandera OK_flag
      }
      Wire.beginTransmission(CTL);            //Envía el byte de control de escritura default (0XA0)
      if (digitalRead(SEL_SW)==0)   //¿Se ha seleccionado el modo smart?
         Wire.write(0);           //Sí, entonces envía la parte alta de la dirección 0x0000
      Wire.write(0);              //Envía la dirección 0x00 (parte baja de 0x0000)
      Wire.write(backup);         //Envía el dato original
      Wire.endTransmission();
      delay(10);              //Espera  10ms para que se escriba el dato
     
      num++;                     //Incrementa el valor de desborde
      if (OK_flag==1)               //¿Se ha levantado la bandera de OK?
         return;               
      else                       //No, entonces
      {
         num = num*2;            //Duplica el valor de desborde
         model = model*2;        //Duplica el modelo de la memoria
         if (num==32)            //¿el modelo de memoria es 24C32?
         {
            num = 128;           //Sí, entonces asigna el valor de desborde para la memoria 24C01
            model = 1;           //Inicializa el modelo de memoria 24C01
         }
      }

      //Serial.print("num= ");
      //Serial.println(num, DEC);
     
   }
   return;     //Termina la subrutina
   
}

void  copy_mem_24C00()
{
  byte i=0, page_buff[16];
  enable_source();      //Enable source memory
  Wire.beginTransmission(CTL);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(CTL,16);
  while(Wire.available())
  {
    page_buff[i] = Wire.read();
    i++;
  }
  enable_target();
  for(i=0; i<16; i++)
  {
    Wire.beginTransmission(CTL);
    Wire.write(i);
    Wire.write(page_buff[i]);
    Wire.endTransmission();
    lcd.setCursor(11,1);
    lcd.print(i, DEC);
    delay(5);
  }
   return;
}

void copy_mem()
{
  byte  page_size,ctl_byte,temp,ee_data[128];
  long  i2c_addr;
 
  page_size = 8;    //Initialize page size of 8 byte
  if((model>2) && (model<17))
    page_size = 16;
  if ((model>31) && (model<65))
    page_size = 32;
  if ((model>127) && (model<257))
    page_size = 64;
  if (model>511)
    page_size = 128;

  i2c_addr = 0;
  while(i2c_addr<=(num-1))
  {
    ctl_byte = CTL;
    if(digitalRead(SEL_SW)==1)
    {
      ctl_byte = (int)(i2c_addr>>8);
      ctl_byte = ctl_byte | CTL;
    }
    if(model>1023)
    {
      ctl_byte = (int)(i2c_addr>>16);
      if(model==1025)
        ctl_byte = ctl_byte<<2;
      ctl_byte = ctl_byte | CTL;
    }

    enable_source();
    Wire.beginTransmission(ctl_byte);
    if(digitalRead(SEL_SW)==0)
      Wire.write((int)(i2c_addr>>8));
    Wire.write((int)(i2c_addr & 0xFF));
    Wire.endTransmission();
    temp = 0;
    Wire.requestFrom(ctl_byte, page_size);
    while(Wire.available())
    {
      ee_data[temp] = Wire.read();
      temp++;
    }

    enable_target();
    Wire.beginTransmission(ctl_byte);
    if(digitalRead(SEL_SW)==0)
      Wire.write((int)(i2c_addr>>8));
    Wire.write((int)(i2c_addr & 0xFF));
    for(temp=0; temp < page_size; temp++)
    {
      Wire.write(ee_data[temp]);
    }
    Wire.endTransmission();
    lcd.setCursor(10,1);
    lcd.print(i2c_addr, DEC);
    if(model < 512)
      delay(10);
    else
      delay(5);
    i2c_addr = i2c_addr + page_size;
  }
  return;
}


Importante:

La librería WIRE de arduino tiene limitado el buffer máximo para escritura a 32 bytes, así que tendremos que editarla para incrementar el buffer a 130 bytes. Para ello debemos editar el archivo Wire.h que se encuentra localizado en:

C:\....\Arduino\hardware\arduino\avr\Wire\src

Originalmente el buffuer está definido así:

Código: [Seleccionar]
#define BUFFER_LENGTH 32

Por lo que hay que cambiarlo a:

Código: [Seleccionar]
#define BUFFER_LENGTH 130

Se recomienda usar un editor de textos como notepad o mejor aún Notepad++

Saludos y cualquier pregunta, por favor no duden en hacerla.

elreypic.


Desconectado Micom

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 757
Re:EEPROM Cloner con Arduino
« Respuesta #2 en: 12 de Diciembre de 2019, 02:09:35 »
Buen trabajo amigo elreypic2
El programador GTP USB PLUS es un super programador
GRACIAS dobles amigo SISPIC

Tan solo queda seguir sobreviviendo

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1093
Re:EEPROM Cloner con Arduino
« Respuesta #3 en: 12 de Diciembre de 2019, 10:45:43 »
Buen trabajo amigo elreypic2

Gracias Micom.

Cualquier duda o sugerencia, nod dudes en hacérmela saber.

elreypic.


 

anything