TODOPIC

Microcontroladores PIC => * PROYECTOS * => Mensaje iniciado por: RedPic en 15 de Octubre de 2006, 12:55:42

Título: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 15 de Octubre de 2006, 12:55:42
 :mrgreen: Circuito y Driver CCS C para 4 Memorias EEPROM I2C 1024 Kbits x 4 : 8 = 512 Kbytes con 4 chips 24AA1025 de Microchip
 
  
Descripción del Proyecto:
  
La finalidad de este proyecto es la de dotar de una cantidad suficiente de memoria no volátil a nuestra RRBOARD2 (http://www.todopic.com.ar/foros/index.php?topic=2300.0). De los varios tipos de memorias no volátiles que podríamos utilizar vamos en este caso a usar una Array de EEPROMS serie externas, todas ellas accesibles mediante un único bus I2C.
 
La idea central es la de desarrollar una Driver en CCS C mediante el que podamos acceder a la totalidad de la memoria disponible "en línea". Desde el primer byte del primer chip hasta el último byte del último chip como si fuese un chip único que englobase la suma de todas las posiciones de memoria direccionables de forma continua.
 
Para este proyecto en concreto vamos a utilizar la EEPROM externa 24AA1025, desarrollada por la gente de Microchip y que han tenido la gentileza de enviarme tres unidades para realizar estos experimentos.
 
Por limitaciones de Hardware inherentes al diseño de las 24AA1025 solo podemos "apilar" un máximo de cuatro unidades de este tipo, por lo que nuestro proyecto va a ceñirse a esta limitación y vamos a diseñar todo en función de este número de elementos.
 
Así la conclusión del proyecto está en leer y/o escribir un byte, mediante las dos funciones correspondientes, en las posiciones de memoria desde 0x00000 hasta 0x7FFFF, ambas inclusive. Un total de 0x80000 posiciones diferentes, o lo que es lo mismo 524.288 posiciones direccionables directamente, lo que significan 524.288 / 1024 = 512 Kbytes.
 
  
Implementación y consideraciones Hardware:
  
Como hemos mas arriba vamos a utilizar para nuestro pequeño proyecto cuatro chips del modelo 24AA1025. Cada uno de ellos dispone de un total de 1024 Kbits lo que significan 1024/8 = 128 Kbytes de memoria, distribuidos en dos bancos de 64 Kbytes cada uno de ellos.
 
Estos chips son accesibles mediante un bus I2C, dos líneas son necesarias para ello: SDA y  SCL con sus correspondientes resistencias Pull-Up a Vcc, que corresponden a los Pines 5 y 6 del chip. Las resistencias Pull-Ups que vamos a utilizar son de 10 KOhmios cada una de ellas.
 
Para direccionar cada uno de los cuatro chips debemos usar las distintas configuraciones hardware que podemos implementar usando los terminales A0 y A1 de cada uno de los chips, Pines 1 y 2 respectivamente, nótese que A2, correspondiente al Pin 3 del chip, no es posible usarlo para este fin ya que ha de ser siempre conectado a Vcc. Estas direcciones hardware posibles combinando A0 y A1 conectándolos a VCC (1) y GND (0) según cada caso son: 00, 01, 10 y 11 y de ahí la limitación a cuatro chips de que hablábamos antes.
 
Podríamos usar el terminal WP, Pin 7 del Chip, para proteger contra escritura nuestra memoria EEPROM ya que éste deshabilita la posibilidad de modificar el contenido de la EEPROM si es conectado a Vcc, pero en este caso no vamos a hacerlo y vamos a conectarlo permanentemente a GND para habilitar siempre la posibilidad de modificación de su contenido.
 
Los Pines 4 y 8 del chip corresponden con la alimentación del mismo y han de ir conectados correspondientemente a GND y VCC.
 
Las distintas funciones de cada uno de los pines puede verse en la siguiente tabla extraída del Datasheet del 24AA1025:

(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-pin-functions.gif)
 
La distribución física de los pines en el Chip es la siguiente:

(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-package.gif)
  
Esquema:
  
Y este es el esquema definitivo que vamos a construir, en el que podemos destacar algunos detalles:
 
.- La comunicación con la RRBOARD2 la realizamos mediante nuestro viejo amigo el conector CON-ML10 para cable plano de 10 hilos (alimentación y un puerto completo de 8 bits)
 
.- JP1-PB y JP2-PC permiten seleccionar la conexión de los SDA y SCL del I2C a los pines 0..1 ó 3..4 del puerto al que estén conectados (recordad de la RRBOARD2 está diseñada para las familias 18F4550 y 16F877 y el I2C lo implementa la primera en los pines RB0 y RB1 y la segunda en los RC3 y RC4)  
 
.- Dependiendo de dónde conectemos nuestro circuito en la RRBOARD2 podemos necesitar o no las resistencias Pull-Up imprescindibles para el bus I2C. Si lo conectamos al PORTB tenemos disponibles la internas del PIC, en cualquier otro caso podemos hacer uso del jumper JP3-PU para conectar dichas resistencias Pull-Up a VCC.
 
.- Por oscuras razones de diseño que ni yo mismo soy capaz de explicarme del todo, a pesar de haber realizado personalmente el mismo, he optado por asignar las direcciones Hardware de cada uno de los chips en orden inverso al natural: Al chip número uno la dirección 11, al dos la 10, al tres la 01 y al cuatro la 00. La verdad es que es irrelevante a la hora de utilizarlos ya que muy fácilmente podremos cambiar la configuración del driver para usar cualquier combinación de direcciones que deseemos utilizar. (Este extremo se verá en detalle en la sección dedicada al driver)
  
(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-schema.gif)

 Circuito impreso:
  
El esquema anterior debidamente ruteado a un tamaño de QUARTER_EUROBOARD genera el siguiente PCB:

(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-board.gif)

Recursos:
  
Datasheet del chip 24AA1025 (http://picmania.garcia-cuervo.net/recursos/redpicdatasheets/24aa1025-24lc1025-24fc1025_21941c.pdf) (PDF 357 Kb)
  
Driver y Software:
  
(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-block.gif)
 
Créditos: Todo lo aquí desarrollado se basa en dos trabajos que no he realizado yo mismo:
 
El programa de ejemplo EX_EXTEE.C de la gente de CCS C (http://www.ccsinfo.com/) y
El Driver Microchip 24AA512 512k I2C EEPROM (http://www.ccsinfo.com/forum/viewtopic.php?t=23390) de UFAnders (http://www.ccsinfo.com/forum/profile.php?mode=viewprofile&u=2373)
 
Pero dejémonos de mas dilaciones innecesarias y entremos en faena con nuestro Driver I2C para memorias EEPROM de gran tamaño:

(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-address-sequence.gif)
  
Según la tabla anterior en que se nos muestra el método I2C de asignar una dirección de memoria a las 24AA1025 para leer o escribir sobre ella, y siguiendo el modo y manera en que CCS C hace uso del bus I2C debemos implementar dos simples funciones que esquemáticamente van a ser como sigue:
 
.- Escribir un byte (data) en una dirección de memoria (memAddress):
Es este caso inicializamos el bus I2C con start(), enviamos con write() el Control Byte, que nosotros llamamos baseAddress, y a continuación los dos bytes de dirección de memoria a escribir, memAddress, empezando con el más significativo y después del menos significativo, seguido del byte, data, que deseamos guardar.
 
Código: C
  1. void writeByte24AA1025(int32 memAddress, int8 data){
  2.   i2c_start();
  3.   i2c_write(baseAddress);
  4.   i2c_write(memAddress>>8);
  5.   i2c_write(memAddress);
  6.   i2c_write(data);
  7.   i2c_stop();
  8. }
  9.  
 
.- Leer un byte de una dirección de memoria (memAddress):
 
Para leer en una posición de memoria debemos realizar el mismo posicionamiento en una dirección de memoria tal como hicimos en la función de escritura seguido de una nueva función start() y una función write() con el bit Read del Control Byte activado. A continuación realizamos un read() del bus I2C y recibiremos el contenido de dicha dirección de memoria.
 
Código: C
  1. int8 readByte24AA1025(int32 memAddress){
  2.  
  3.   int8 returnByte=0;
  4.  
  5.   i2c_start();
  6.   i2c_write(baseAddress);
  7.   i2c_write(memAddress>>8);
  8.   i2c_write(memAddress);
  9.   i2c_start();
  10.   i2c_write(baseAddress|1);
  11.   returnByte = i2c_read(0);
  12.   i2c_stop();
  13.   return returnByte;
  14. }
  15.  

Todo esto está muy bien en principio pero hay una serie de importantes detalles que no hemos tomado en cuenta aún y que son imprescindibles si deseamos llevar a buen puerto nuestro proyecto:
 
(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-control-byte.gif)
 
En primer lugar está el asunto que cómo configurar apropiadamente el Control Byte. Es un único Byte y en él debemos incluir:
 
El Control Code. Que siempre son los mismo Bits, 7..4, y que para estos chips es 1010.
 
El Block Select Bit. Que indica en que Banco de los dos de 65535 bytes que tiene cada chip es al que nos estamos refiriendo.
 
El Chip Select Bits. Que es la dirección por Hardware que le asignamos a cada uno de los cuatro chips con los que estamos trabajando.
 
El Read/Write bit. Donde indicamos si estamos leyendo o escribiendo una posición de memoria.
 
En segundo lugar debemos hacer una conversión de la dirección de memoria donde queremos escribir desde la absoluta que enviamos a nuestras funciones, entre 0x00000 y 0x7FFFF, a la relativa de Chip/Banco/0x0000 a 0x1FFFF que es la máxima dirección accesible dentro de un Banco dentro de un Chip en concreto.
 
O sea que en función de la dirección absoluta que enviemos a nuestras funciones debemos componer el Control Byte seleccionando el Chip al que nos referimos, el Banco dentro de ese chip y la dirección concreta por la que estamos preguntando.
 
Partimos de una Control Byte base de: int8 const baseAddress24AA1025 = 0b10100000;
 
Y le configuramos los distintos bits. Esto lo solventamos con las siguientes funciones auxiliares:
 
int8 memAbsoluteAddress2deviceOrder(int32 memAddress);
 
Que nos devuelve 1, 2, 3 ó 4 dependiendo de si memAddress es mayor 0x00000 y menor que 0x1FFFF, ó es mayor que 0x20000 y menor que 0x3FFFF ... etc. etc.

int8 memAbsoluteAddress2deviceAddress(int32 memAddress);
 
Que nos devuelve la dirección Hardware del Chip 1, 2, 3 ó 4 al que corresponde la dirección absoluta memAddress. Esta dirección hardware es la parte Chip Select Bits del Control Byte.
 
Estas deciveAddress las extraemos en función del anterior deviceOrder haciendo uso de la siguiente tabla de asignación de direcciones Hardware:
 
Código: C
  1. // device hardware address
  2. int8 const deviceAddress1 = 0b00000011; // #3
  3. int8 const deviceAddress2 = 0b00000010; // #2
  4. int8 const deviceAddress3 = 0b00000001; // #1
  5. int8 const deviceAddress4 = 0b00000000; // #0
  6.  

int32 memAbsoluteAddress2menRelativeAddress(int8 deviceOrder,int32 memAddress);

Que nos va a ajustar memAddress a la dirección relativa dentro de cada uno de los Chip, haciendo que cada una de ellas comienze realmente en 0x00000.

int1 menRelative2BankSelect(int32 memRelativeAddress);

Y ésta que por último nos selecciona el Banco, alto o bajo, de cada uno de los Chips. Corresponde al Block Select Bit del Control Byte.
 
Con todo esto podemos ya completar nuestras funciones principales, añadiéndoles las cabeceras correspondientes para ajustar todos y cada uno de los parámetros:
 
Código: C
  1.   int8 baseAddress;
  2.   int8 deviceAddress;
  3.   int8 deviceOrder=0;
  4.   int32 memRelativeAddress;
  5.   int8 bank=0;
  6.  
  7.   deviceAddress = memAbsoluteAddress2deviceAddress(memAddress);
  8.   deviceOrder = memAbsoluteAddress2deviceOrder(memAddress);
  9.   memRelativeAddress = memAbsoluteAddress2menRelativeAddress(deviceOrder, memAddress);
  10.   bank = menRelative2BankSelect(memRelativeAddress);
  11.   baseAddress = baseAddress24AA1025 + (bank<<3) + (deviceAddress<<1);
  12.  

El driver definitivo queda así:
 
Código: C
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // 4 x EEPROM 24AA1025 Driver with absolute memory addressing
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////
  6.  
  7. #define EEDEBUG
  8.  
  9. // device hardware address
  10.  
  11. int8 const deviceAddress1 = 0b00000011; // #3
  12. int8 const deviceAddress2 = 0b00000010; // #2
  13. int8 const deviceAddress3 = 0b00000001; // #1
  14. int8 const deviceAddress4 = 0b00000000; // #0
  15.  
  16. // baseAddress = 8 bits which mean ...
  17. //
  18. // Fixed (4 bits)            -> 1010
  19. // EE internal Block (1 bit) -> 0 for 0000/FFFF, 1 for 10000/1FFFF
  20. // Dev Hard Address (2 bits) -> 00 or 01 or 10 or 11
  21. // R/W (1 bit)               -> 0 -> Write / 1 -> Read
  22.  
  23. int8 const baseAddress24AA1025 = 0b10100000;
  24.  
  25. // Aux Functions //////////////////////////////////////////////////////////////
  26.  
  27. int1  menRelative2BankSelect(int32 memRelativeAddress){
  28.  
  29.    int1 returnBit=0;
  30.  
  31.    if(memRelativeAddress>(int32) 0xffff) returnBit = 1;
  32.  
  33.    return returnBit;
  34. }
  35.  
  36. int32 memAbsoluteAddress2menRelativeAddress(int8 deviceOrder, int32 memAddress){
  37.  
  38.    int32 returnInt32 = 0;
  39.  
  40.    switch(deviceOrder){
  41.       case 1: returnInt32 = memAddress;
  42.               break;
  43.       case 2: returnInt32 = memAddress - 0x20000;
  44.               break;
  45.       case 3: returnInt32 = memAddress - 0x40000;
  46.               break;
  47.       case 4: returnInt32 = memAddress - 0x60000;
  48.               break;
  49.    }
  50.    return returnInt32;
  51. }
  52.  
  53. int8 memAbsoluteAddress2deviceOrder(int32 memAddress){
  54.  
  55.    int8  returnByte=0;
  56.  
  57.    if((memAddress>0x05ffff)&&(memAddress<0x080000)) returnByte=4;
  58.    if((memAddress>0x03ffff)&&(memAddress<0x060000)) returnByte=3;
  59.    if((memAddress>0x01ffff)&&(memAddress<0x040000)) returnByte=2;
  60.    if(                       (memAddress<0x020000)) returnByte=1;
  61.  
  62.    return returnByte;
  63. }
  64.  
  65. int8 memAbsoluteAddress2deviceAddress(int32 memAddress){
  66.  
  67.    int8  deviceOrder=0, returnByte=0;
  68.  
  69.    deviceOrder = memAbsoluteAddress2deviceOrder(memAddress);
  70.  
  71.    switch(deviceOrder){
  72.       case 0: returnByte = 0xff;
  73.               break;
  74.       case 1: returnByte = deviceAddress1;
  75.               break;
  76.       case 2: returnByte = deviceAddress2;
  77.               break;
  78.       case 3: returnByte = deviceAddress3;
  79.               break;
  80.       case 4: returnByte = deviceAddress4;
  81.               break;
  82.    }
  83.    return returnByte;
  84. }
  85.  
  86. // Main Functions /////////////////////////////////////////////////////////////
  87.  
  88. void writeByte24AA1025(int32 memAddress, int8 data){
  89.  
  90.    int8  baseAddress;
  91.    int8  deviceAddress;
  92.    int8  deviceOrder=0;
  93.    int32 memRelativeAddress;
  94.    int8  bank=0;
  95.  
  96.    deviceAddress      = memAbsoluteAddress2deviceAddress(memAddress);
  97.    deviceOrder        = memAbsoluteAddress2deviceOrder(memAddress);
  98.    memRelativeAddress = memAbsoluteAddress2menRelativeAddress(deviceOrder, memAddress);
  99.    bank               = menRelative2BankSelect(memRelativeAddress);
  100.    baseAddress        = baseAddress24AA1025 + (bank<<3)  + (deviceAddress<<1);
  101.    
  102. #ifdef EEDEBUG
  103.    printf("\r\n\nAbsolute Address: %LX Relative Address: %Lx Device: %u Bank: %u\r\n",memAddress,memRelativeAddress,deviceOrder,bank);
  104. #endif
  105.  
  106.    i2c_start();
  107.    i2c_write(baseAddress);
  108.    i2c_write(memAddress>>8);
  109.    i2c_write(memAddress);
  110.    i2c_write(data);
  111.    i2c_stop();
  112.    delay_ms(5);
  113. }
  114.  
  115. int8 readByte24AA1025(int32 memAddress){
  116.  
  117.    int8  returnByte=0;
  118.    int8  baseAddress;
  119.    int8  deviceAddress;
  120.    int8  deviceOrder=0;
  121.    int32 memRelativeAddress;
  122.    int8  bank=0;
  123.  
  124.    deviceAddress      = memAbsoluteAddress2deviceAddress(memAddress);
  125.    deviceOrder        = memAbsoluteAddress2deviceOrder(memAddress);
  126.    memRelativeAddress = memAbsoluteAddress2menRelativeAddress(deviceOrder, memAddress);
  127.    bank               = menRelative2BankSelect(memRelativeAddress);
  128.    baseAddress        = baseAddress24AA1025 + (bank<<3)  + (deviceAddress<<1);
  129.  
  130. #ifdef EEDEBUG
  131.    printf("\r\n\nAbsolute Address: %LX Relative Address: %Lx Device: %u Bank: %u\r\n",memAddress,memRelativeAddress,deviceOrder,bank);
  132. #endif
  133.  
  134.    i2c_start();
  135.    i2c_write(baseAddress);
  136.    i2c_write(memRelativeAddress>>8);
  137.    i2c_write(memRelativeAddress);
  138.    i2c_start();
  139.    i2c_write(baseAddress|1);
  140.    returnByte = i2c_read(0);
  141.    i2c_stop();
  142.    return returnByte;
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////
  145.  

Como os dije mas arriba el siguiente programa es una adaptación del programa de ejemplo EX_EXTEE.C de la gente de CCS C que podéis encontrar en el directorio examples de la instalación de dicho compilador.
  
Código: C
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // EEPROM_24AA1025x1.C
  4. //
  5. // by RedPic from http://picmania.garcia-cuervo.net
  6. //
  7. // October 2006
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include <18F4550.h>
  12. #fuses HS,NOWDT,NOPROTECT,NOLVP
  13. #use delay(clock=20000000)
  14. #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
  15. #use i2c(master, sda=PIN_B0, scl=PIN_B1)
  16.  
  17. #include <input.c>
  18. #include <24AA1025x4.c>
  19.  
  20. const char Version[]="1.0.F\0";
  21.  
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // Main
  25. //
  26. ///////////////////////////////////////////////////////////////////////////////
  27.  
  28. void main() {
  29.  
  30.    BYTE value, cmd;
  31.    int32 address;
  32.    int8  device;
  33.  
  34.    delay_ms(300);
  35.    printf("\r\n\n");
  36.    printf("[RRBOARD2] EEPROM Total Commander %s\r\n",version);
  37.    printf("based on 24AA1025 Microchip Hardware\r\n");
  38.    printf("\xa9 10.2006 by RedPic\r\n\n");
  39.  
  40.    do {
  41.  
  42.       do {
  43.          printf("\r\nDo you Read or Write? : ");
  44.          cmd=getc();
  45.          cmd=toupper(cmd);
  46.          putc(cmd);
  47.       } while ( (cmd!='R') && (cmd!='W') );
  48.  
  49.       printf("\n\rGive me EEPROM internal absolute Address (24 bits) in hex : ");
  50.  
  51.       address = gethex();
  52.       address = (address<<8)+gethex();
  53.       address = (address<<8)+gethex();
  54.  
  55.       device  = memAbsoluteAddress2deviceAddress(address);
  56.  
  57.       if(cmd=='R')
  58.          printf("\r\nReturn Value (8 bits) in hex is : %X\r\n",readByte24AA1025(address));
  59.  
  60.       if(cmd=='W') {
  61.          printf("\r\nEnter new value (8 bits) in hex : ");
  62.          value = gethex();
  63.          printf("\n\r");
  64.          writeByte24AA1025(address, value );
  65.       }
  66.    } while (TRUE);
  67. }
  68.  

Funcionando:
  
Para realizar las primeras pruebas he realizado físicamente el siguiente esquema y PCB que implementa uno de estos chips 24AA1025:
 
(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-minimo-board.gif)  

 
(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-minimo-foto.jpg)

  
(http://picmania.garcia-cuervo.net/images/quad-eeprom-i2c-minimo-dump-02.gif)
 
Ea, ahí queda eso. Mañana más.   :mrgreen: :-/ :mrgreen:

Nota: El driver en CCS C definitivo está a partir de este post (http://www.todopic.com.ar/foros/index.php?topic=14328.msg118819#msg118819) (Enero 2008)
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: samshiel_pic en 15 de Octubre de 2006, 15:21:25
Increible Diego  :shock: cada vez me sorprendes más, esta novela me viene como anillo al dedo  :D.

Yo estoy intentando implementar una serie de memorias para guardar la hora y la fecha en la que sucenden una serie de eventos. En principio seria que cada vez que pulse un boton o pulsador me guarde la la hora y la fecha en la que lo he pulsado y posteriormente poder ver en un lcd o en el hyperterminal todo lo guardado. Para ello utilizaria gran parte de tu otra novela DS1307 desatado  (http://www.todopic.com.ar/foros/index.php?topic=13282.0) jejeje. Una vez que esto este funcionando lo acoplaria a otro proyecto que tengo entre manos para monitorizar cuando y a que hora salta el dispositivo.
Pero todavia toy un poco pez. Tendre que estudiarlo muy detenidamente :P
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 15 de Octubre de 2006, 15:34:38
Si amigo Samshiel_pic, para una cosa parecida lo necesito yo. :mrgreen:

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: samshiel_pic en 15 de Octubre de 2006, 15:50:20
Espero noticias sobre ello amigo :P
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: vinny en 18 de Diciembre de 2006, 14:01:27
Hola , me he estado mirando el código de RedPic y creo qua falta inicializar la eeprom, tal y como sale en los drivers originales para las eeproms externas, no? deberia ser algo así:

ifndef EEPROM_SDA

#define EEPROM_SDA  PIN_B1
#define EEPROM_SCL  PIN_B0

#endif

#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)

#define EEPROM_ADDRESS long int
#define EEPROM_SIZE   32768

/// y dentro del main poner
void init_ext_eeprom()
{
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);

}

el resto dejarlo tal cual, vamos, esa me parece a mi, no se
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: vinny en 18 de Diciembre de 2006, 14:56:19
 Ola, creo que he encontrado un fallo en el código:

donde dice:
// device hardware address

int8 const deviceAddress1 = 0b00000011; // #3
int8 const deviceAddress2 = 0b00000010; // #2
int8 const deviceAddress3 = 0b00000001; // #1
int8 const deviceAddress4 = 0b00000000; // #0

// baseAddress = 8 bits which mean ...
//
// Fixed (4 bits)            -> 1010
// Dev Hard Address (3 bits) -> 000,001,010,011,100,101,110,111
// R/W (1 bit)               -> 0 -> Write / 1 -> Read

el ultimo bit de las constantes deviceAddress debe ser 0, el ultimo bit es el bit R/W no es ninguna direccion, se te han recorrido los bits al escribir, deberia quedar así:
// device hardware address

int8 const deviceAddress1 = 0b00000110; // #3
int8 const deviceAddress2 = 0b00000100; // #2
int8 const deviceAddress3 = 0b00000010; // #1
int8 const deviceAddress4 = 0b00000000; // #0



Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 18 de Diciembre de 2006, 19:07:10
No amigo vinny, no es un error, está expresando exactamente lo que dice que es: el DeviceAddress.

Las direcciones de los distintos chips solamente pueden ponerse con dos bits, en esta clase de memorias EEPROM, o sea que solo pueden ser 00, 01, 10 y 11.

Escritos como bytes deben ser completados con ceros por la izquierda. Tal como lo tengo en las constantes. Son las direcciones hard de cada uno de los chips, no el baseAddress.

El baseAddress es la palabra de selección de Descritor de Dispositivo + Block Select + Hard DeviceAddress + Function R/W para las funciones i2C y esta se compone cuando hago el

baseAddress  = baseAddress24AA1025 + (bank<<3)  + (deviceAddress<<1);

fíjate que deviceAddress lo desplazo un bit a la izquierda para dejarle sitio al último bit que es el de R/W.






Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: vinny en 20 de Diciembre de 2006, 07:56:42
Tienes razón, no me habia dado cuenta de ese detalle :-)

Creo que podrias ahorrar mucho código si donde pones las deviceAddress escribieses las 8 posibles baseaddress que tienes y luego cuando vayas a escribir por I2C, haces un switch y le dices la baseaddress directamente. habria q hacer los if's de escoger la memoria y el banco por tamaño, y ya está.
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 20 de Diciembre de 2006, 11:23:07
Decía un militar USA que para montar un buen follón hace falta un buen ordenador ...  :D :D :D :D

Si para encender un Led escribo un output_high(Pin) entonces no tiene gracia ...
Tengo que hacer un #define del puerto, asignarle un nombre extraño, hacerle read del puerto completo y un AND lógico con el byte cuyo bit que corresponda al pin que deseo activar esté en alto y escribir con él directamente en el Latch de salida ...  :D :D :D :D

Perdon, pero es que me ofusco .... y yo solo me lio conmigo mismo y mis funciones de funciones de funciones (While true)  :D :D :D :D

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: vinny en 20 de Diciembre de 2006, 20:55:39
 :( perdon, cada uno lo hace como cree conveniente o como se lia menos...pero...es q yo soy catalán, y ahorro hasta en el código :D :D :D :D :D :D
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 21 de Diciembre de 2006, 02:10:03
muy buena, muy buena ja ja ja  :D :D :D :D :D :D :D :D :D :D :D
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: Nocturno en 21 de Diciembre de 2006, 03:26:04
Jeje, pues no eres el único catalán que conozco que es un maniático ahorrando código...  :mrgreen:
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: pikman en 03 de Enero de 2007, 10:52:05
Estimado Red ante todo gracias por compartir todo lo que conoces y haces, es un ejemplo de vida, estoy modificando el codigo para usar 8 24lc512 porque necesito 512K, pero no consigo aqui las 241025, de hecho no es muy complicado, pero en esta funcion creo que hay un error o tu me  diras si estoy equivocado.

int8 memAbsoluteAddress2deviceOrder(int32 memAddress){

   int8  returnByte=0;

   if((memAddress>0x05ffff)&&(memAddress<0x080000)) returnByte=4;
   if((memAddress>0x03ffff)&&(memAddress<0x060000)) returnByte=3;
   if((memAddress>0x01ffff)&&(memAddress<0x040000)) returnByte=2;
   if(                       (memAddress<0x020000)) returnByte=1;

   return returnByte;
}

Si la direccion absoluta es 0x3ffff o 0x60000, 0x01ffff o 0x040000 , o 0x020000, la funcion retorna 0, no deberia ser:

int8 memAbsoluteAddress2deviceOrder(int32 memAddress){

   int8  returnByte=0;

   if((memAddress>=0x05ffff)&&(memAddress<=0x080000)) returnByte=4;
   if((memAddress>=0x03ffff)&&(memAddress<=0x060000)) returnByte=3;
   if((memAddress>=0x01ffff)&&(memAddress<=0x040000)) returnByte=2;
   if(                       (memAddress<=0x020000)) returnByte=1;

   return returnByte;
}

Pues de la otra manera las direcciones que delimitan cada byte de retorno ( que no son muchas 7 bytes ) no son accesibles.
Para simplificar si apunto a la direccion 0x01ffff retorna el byte 1 pero si apunto la direccion 0x020000 retorna el byte en 0, pues 0x20000 no es menor ni mayor, por eso aguegue el operador de igualdad, entonces si memAddress es menor o igual a 0x20000 retorna 1.

ademas esta linea

   if((memAddress>=0x01ffff)&&(memAddress<=0x040000)) returnByte=2;

no deberia ser

   if((memAddress>=0x02ffff)&&(memAddress<=0x040000)) returnByte=2;


O no se donde estoy equivocado, desde ya gracias por responder.

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: LordLafebre en 03 de Enero de 2007, 12:10:26
Hola:

Pues solamente felicitar a Diego por sus grandes aportes, sobretodo por la explicacion.

PD: Para cuando sacas el libro? ya solo debes recopilar tus temas posteados  :mrgreen:
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: Sispic en 03 de Enero de 2007, 13:59:38
Esto ahorraria un monton de codigo catalanes .
Hecha la ley ..hecha la trampa .

Ejemplo .

Código: [Seleccionar]
typedef struct  {
     int1 b0:1; int1 b1:1; int1 b2:1;  int1 b3:1;  int1 b4:1;  int1 b5:1;  int1 b6:1;  int1 b7:1;
} Los_bits_de_un_Byte;


typedef struct {
        int8 byte0;
        int8 byte1;
        int8 byte2;

} My_Address;

/**************************************************************/

void writeByte24AA1025(My_Address memAddress, int8 data){

   Los_bits_de_un_Byte temp , ControlByte;
   
   temp = memAddress.byte2 ;
     
   ControlByte = 0b10100000; // 0xA0 - bit0 Write = 0

   ControlByte.b3 = temp.b0 ; // Block Select Bit
   ControlByte.b1 = temp.b1;  // Chip Select Bit0
   ControlByte.b2 = temp.b2 ; // Chip Select Bit1

   i2c_start();
   i2c_write((int8)ControlByte);
   i2c_write(memAddress.byte1); // Address High Byte
   i2c_write(memAddress.byte0); // Address Low Byte
   i2c_write(data);
   i2c_stop();
   delay_ms(5);
}

Y para una 24AA512 , pocos cambios

Código: [Seleccionar]
void writeByte24AA512(My_Address memAddress, int8 data){

   Los_bits_de_un_Byte temp , ControlByte;
   
   temp = memAddress.byte2 ;
   
   ControlByte = 0b10100000; // 0xA0 - bit0 Write = 0

   ControlByte.b1 = temp.b0 ; // Chip Select Bit0
   ControlByte.b2 = temp.b1 ; // Chip Select Bit1
   ControlByte.b3 = temp.b2 ; // Chip Select Bit2

   i2c_start();
   i2c_write((int8)ControlByte);
   i2c_write(memAddress.byte1); // Address High Byte
   i2c_write(memAddress.byte0); // Address Low Byte
   i2c_write(data);
   i2c_stop();
   delay_ms(5);
}



No lo he provado , no me tireis a los leones si no va  :D
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: pikman en 03 de Enero de 2007, 15:38:05
Es increible, increible........ademas de ahorrar codigo ahorra RAM y ROM......a veces pienso que nunca voya terminar de aprender a usar la cabeza...!!!! :mrgreen: :mrgreen:
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: pikman en 03 de Enero de 2007, 19:03:02
Bueno Sisco, ademas de darte las gracias por la ayuda te digo que el driver va como viento, funciona perfectamente, con las 24C512 y las 24C515 o 1025, muy economico por cierto :D :D
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 03 de Enero de 2007, 19:18:38
Ufff ... he llegado tarde a la solución de mis propios errores  :mrgreen:

Pikman, ¿te importaría postear el código completo del driver tal como ha quedado?

Sisco, muchas gracias por tu aporte y tu interés en estos inventos.  :D

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: pikman en 03 de Enero de 2007, 19:54:47
Hola, DIEGO, pues como no aca esta, no difiere mucho de lo posteado, yo agregue la lectura, y la inicializacion del bus y los puertos, de cualquier modo no se si miraste la duda que te deje en le codigo tuyo

Código: [Seleccionar]

#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)

void init_ext_eeprom()
{
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);

}


typedef struct  {
     int1 b0:1; int1 b1:1; int1 b2:1;  int1 b3:1;  int1 b4:1;  int1 b5:1;  int1 b6:1;  int1 b7:1;
} Los_bits_de_un_Byte;


typedef struct {
        int8 byte0;
        int8 byte1;
        int8 byte2;

} My_Address;



void writeByte24512(My_Address memAddress, int8 data){

   short int status;

   Los_bits_de_un_Byte temp , ControlByte;

   temp = memAddress.byte2 ;

   ControlByte = 0b10100000; // 0xA0 - bit0 Write = 0

   ControlByte.b1 = temp.b0 ; // Chip Select Bit0
   ControlByte.b2 = temp.b1 ; // Chip Select Bit1
   ControlByte.b3 = temp.b2 ; // Chip Select Bit2

   i2c_start();
   i2c_write((int8)ControlByte);
   i2c_write(memAddress.byte1); // Address High Byte
   i2c_write(memAddress.byte0); // Address Low Byte
   i2c_write(data);
   i2c_stop();
   delay_ms(5);
}




int8 readByte24512(My_Address memAddress){

   int8 data;

   Los_bits_de_un_Byte temp,ControlByte;

   temp = memAddress.byte2 ;

   ControlByte = 0b10100000; // 0xA0 - bit0 Write = 0

   ControlByte.b1 = temp.b0 ; // Chip Select Bit0
   ControlByte.b2 = temp.b1 ; // Chip Select Bit1
   ControlByte.b3 = temp.b2 ; // Chip Select Bit2

   i2c_start();
   i2c_write((int8)ControlByte);
   i2c_write(memAddress.byte1); // Address High Byte
   i2c_write(memAddress.byte0); // Address Low Byte
   i2c_start();
   i2c_write((int8)ControlByte|1);
   data=i2c_read(0);
   i2c_stop();
   return data;

}

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 04 de Enero de 2007, 03:21:32
No, amigo pikman, aún no lo he mirado. Estoy de trabajo hasta las orejas y no he tenido tiempo de ponerme con él. (Pero lo haré, vive diós que lo haré ja ja ja  :D :D :D)

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: pikman en 04 de Enero de 2007, 10:26:36
Hola, RED,  mira hice una prueba con el dirver para ver si funcionaba correctamente, escribiendo y leyendo cada posicion de memoria, desde 0 hasta 0x7FFF, y funciono correctamente, ademas la perfomace poco difiere a utilizar una sola memoria, pues en mi caso se almacenan datos que despues se transfieren a una PC con un protocolo propietario de correccion de errores bastante lento, pero con esto va muy bien, gracias a ti y a Sisco por supuesto.
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: pikman en 08 de Enero de 2007, 01:38:28
Por aca de nuevo, con mi version de driver, espero que les guste, claro que no voy a ganar en ahorro a Sispic, pero bueno una alternativa, que funciona tambien correctamente, y aplicable a casi todas las 24xxx que permiten direccionamiento por harware, solo lo he usado con las 24LC512 pero si se fijan como funciona la 1025 creo que funcionaria tambien sin modificaciones pero bueno no lo probe.

suerte.

Código: [Seleccionar]


///////////////////////////////////////////////////////////////////////////////////
////       Libreria para acceso lineal de 8 chips 24LC512                      ////
////                                                                           ////
////         Direccionamiento lineal de 0-0x7FFFF (512KBytes)                  ////
////       Provee la facilidad de usar hasta 8 chips como si fuese 1 solo      ////                                                                         ////
//// init_24512x8();  inicializa el bus                                        ////
////                                                                           ////
//// writeByte24512x8(a,d); escribir el byte d(int8) en la direccion a(int32)  ////
////                                                                           ////
//// d=ReadByte24512x8(a); lee el byte d(int8) desde la direccion a(int32)     ////
////                                                                           ////
////                                                                           ////
///////////////////////////////////////////////////////////////////////////////////



#ifndef EEPROM_SDA

#define EEPROM_SDA  PIN_B1
#define EEPROM_SCL  PIN_B0

#endif

#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)

#define MULTIPLE_EEPROM_ADDRESS int32
#define EEPROM_SIZE   524288

void init_ext_eeprom()
{
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);

}


void writeByte_24512x8(int32 memaddress, int8 data){

   int16 address;
   int8  controlbyte;
   short int status;
   
   address=memaddress;

   controlbyte=(0xa0 | ((make8(memaddress,2))<<1));

   i2c_start();
   i2c_write(controlbyte);
   i2c_write(address>>8);     
   i2c_write(address);         
   i2c_write(data);           
   i2c_stop();
   // AckNolege pooling
   i2c_start();
   status=i2c_write(controlbyte);
   while(status==1)
   {
   i2c_start();
   status=i2c_write(controlbyte);
   }
   i2c_stop();
}



int8 readByte_24512x8(int32 memaddress){

    int16 address;
    int8  controlbyte;
    int8  data;

    address=memaddress;
    controlbyte=(0xa0 | ((make8(memaddress,2))<<1));


    i2c_start();
    i2c_write(controlbyte);
    i2c_write(address>>8);
    i2c_write(address);             
    i2c_start();
    i2c_write(controlbyte|1); 
    data=i2c_read(0);
    i2c_stop();
    return data;
}



Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 08 de Junio de 2007, 07:29:27
Versión definitiva (por ahora) del Driver. Está probado y funciona a las mil maravillas.  :mrgreen:

Código: CSS
  1. /** \file Driver_24AA1025.c
  2.  * \brief Este fichero contiene funciones para el uso de las memorias Serial EEPROM mediante el bus I2C.
  3.  *
  4.  * Tiene capacidad para hasta 4 módulos de tipo 24AA1025 de Microchip,
  5.  * direcionadas individualmente mediante las constantes <b>deviceAddressX</b>
  6.  * correspondientes a las direcciones hardware de los chips.
  7.  *
  8.  * <b>¡Atención!</b> No inicia la comuniación I2C que debe ser iniciada externamente.
  9.  *
  10.  * \author Diego RedPic
  11.  */
  12.  
  13. // baseControlByte24AA1025 = 8 bits which mean ...
  14. //
  15. // Fixed (4 bits)            -> 1010
  16. // EE internal Block (1 bit) -> 0 for 0000/FFFF, 1 for 10000/1FFFF
  17. // Dev Hard Address (2 bits) -> 00 or 01 or 10 or 11
  18. // R/W (1 bit)               -> 0 -> Write / 1 -> Read
  19.  
  20. int8 const baseControlByte24AA1025 = 0b10100000;
  21. //                                     ----B10W
  22.  
  23.  
  24. // Aux Function /////////////////////////////////////////////////////////////
  25.  
  26. /** \brief Función para la escritura de un byte dando su valor y su dirección absoluta.
  27.   *
  28.   * Esta función decodifica la Dirección Absoluta de memoria en Dirección Relatiba, Banco y Device en las 24AA1025.
  29.   * \param absAddress Dirección absoluta de 32 bits a escribir (rango de 000000h a 080000h).
  30.   * \param[out] relAddress Direccion interna relativa (rango de 0000h a FFFFh).
  31.   * \param[out] cByte Composición del byte de cabecera que incluye el Banco y el Device.
  32.   * \return void
  33.   *
  34.   */
  35. void absoluteAddress_to_relativeAddressAndControlByte24AA1025(int32 absAddress, int16 &relAddress, int8 &cByte){
  36.  
  37.    int8 i;
  38.  
  39.    // Relative Address (Copiar los primeros 16 bits)
  40.    relAddress = 0;
  41.    for(i=0;i<16;i++){
  42.       if(bit_test(absAddress,i)==1){
  43.          bit_set(relAddress,i);
  44.       }
  45.    }
  46.    // Inicializa Control Byte
  47.    cByte = baseControlByte24AA1025;
  48.    // Bank
  49.    if(bit_test(absAddress,16)==1){
  50.       bit_set(cByte,3);
  51.    }
  52.    // Device A0
  53.    if(bit_test(absAddress,17)==1){
  54.       bit_set(cByte,1);
  55.    }
  56.    // Device A1
  57.    if(bit_test(absAddress,18)==1){
  58.       bit_set(cByte,2);
  59.    }
  60. }
  61.  
  62. // Main Functions /////////////////////////////////////////////////////////////
  63.  
  64.  
  65. /** \brief Función para la escritura de un byte dando su valor y su dirección absoluta en las 24AA1025
  66.   *
  67.   * Esta función incluye \c <b>delay</b> de 5 milisegundos tras su ejecución ¡NO DISMINUIR!.
  68.   * \param Address Dirección absoluta de 32 bits a escribir (rango de 000000h a 080000h).
  69.   * \param data Valor del byte a escribir (rango de 00h a ffh).
  70.   * \return void
  71.   */
  72. void writeByte24AA1025(int32 Address, int8 data){
  73.  
  74.    int8  controlByte;
  75.    int16 relativeAddress;
  76.  
  77.    absoluteAddress_to_relativeAddressAndControlByte24AA1025(Address,relativeAddress,controlByte);
  78.  
  79.    i2c_start();
  80.    i2c_write(controlByte);
  81.    i2c_write(relativeAddress>>8);
  82.    i2c_write(relativeAddress);
  83.    i2c_write(data);
  84.    i2c_stop();
  85.    delay_ms(5);
  86. }
  87.  
  88. /** \brief Función para la lectura de un byte dando su dirección absoluta en las 24AA1025
  89.   *
  90.   * \param Address Dirección absoluta de 32 bits a leer (rango de 000000h a 080000h).
  91.   * \return Devuelve byte (int8) con el contenido de dicha dirección.
  92.   */
  93. int8 readByte24AA1025silent(int32 Address){
  94.  
  95.    int8  returnByte=0;
  96.    int8  controlByte;
  97.    int16 relativeAddress;
  98.  
  99.    absoluteAddress_to_relativeAddressAndControlByte24AA1025(Address,relativeAddress,controlByte);
  100.  
  101.    i2c_start();
  102.    i2c_write(controlByte);
  103.    i2c_write(relativeAddress>>8);
  104.    i2c_write(relativeAddress);
  105.    i2c_start();
  106.    i2c_write(controlByte|1);
  107.    returnByte = i2c_read(0);
  108.    i2c_stop();
  109.    return returnByte;
  110. }
  111.  
  112. /** \brief Función para la lectura de un string en las 24AA1025 dando su dirección absoluta y su longitud.
  113.   *
  114.   * \param Address Dirección absoluta de 32 bits a leer (rango de 000000h a 080000h).
  115.   * \param Len Longitud de 8 bits de datos a leer (rango de 00h a FFh).
  116.   * \param[out] pF Puntero con el contenido de lo leído. Se carga de pF[0] a pF[Len-1] y se fuerza pF[Len] a \\0.
  117.   * \return void
  118.   */
  119. void readString24AA1025(int32 Address, int8 Len, char* pF){
  120.  
  121.    char  c;
  122.    int32 m;
  123.    int8  i;
  124.  
  125.    set_to_i2c_channel();
  126.    for(i=0,m=Address;i<Len;i++,m++){
  127.       c = readByte24AA1025silent(m);
  128.       pf[i]=c;
  129.    }
  130.    pf[Len]='\0';
  131.    set_to_ext_channel();
  132. }
  133.  
  134. /** \brief Función para de escritura de un campo en las 24AA1025 dando su dirección absoluta y su contenido.
  135.   *
  136.   * \param Address Dirección absoluta de 32 bits del primer byte del campo a escribir (rango de 000000h a 080000h).
  137.   * \param Len Longitud de 8 bits de datos a leer (rango de 00h a FFh).
  138.   * \param pF Puntero con el contenido del string que hay que escribir.
  139.   * \return void
  140.   */
  141. void writeString24AA1025(int32 Address, int8 Len, char* pF){
  142.  
  143.    int8  i;
  144.    int32 m;
  145.  
  146.    for(i=0,m=Address;i<Len_string,i<Len;i++,m++){
  147.       writeByte24AA1025silent(m,pF[i]);
  148.    }
  149. }
  150.  
  151. /** \brief Función que rellena las 24AA1025 desde una dirección absoluta de inicio hasta una de final y el carácter de relleno.
  152.   *
  153.   * \param Start_Address Dirección de inicio del volcado de momoria
  154.   * \param End_Address Dirección final del volcado de momoria
  155.   * \param FillChar Valor del Byte de relleno
  156.   *
  157.   * \return void
  158.   */
  159. void FillMemory24AA1025(int32 Start_Address, int32 End_Address, int8 FillChar){
  160.  
  161.    int32 m;
  162.  
  163.    for(m=Start_Address;m<End_Address+1;m++){
  164.       writeByte24AA1025silent(m,FillChar);
  165.    }
  166. }
  167.  
  168. ///////////////////////////////////////////////////////////////////////////////
  169.  

Lo de los 5 milisegundos tras cada escritura es crítico. Poniendo 4 milisegundos se produce un error de cada tres escrituras. Con 3 milisegundos falla el 50% de las escrituras. Con esos 5 milisegundos no he tenido ningún error en miles de escrituras.

Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbyt
Publicado por: Meta en 23 de Enero de 2008, 15:05:08
Podrías poner el Data Source del esto:

(http://picmania.garcia-cuervo.net/images/AUX_Max232_PCCOM1.JPG)

Me encanta esa interfaz y verla funcionar.
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbyt
Publicado por: RedPic en 23 de Enero de 2008, 18:07:19
No, va ser que no. Esta es una de las miles de utilidades que tengo por mi PC y no se ni de quien es.
Título: Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
Publicado por: RedPic en 26 de Junio de 2009, 18:18:25
Actualizados todos los enlaces de imágenes en este hilo (estaban corruptas tras mi último cambio de servidor)  :mrgreen:

Un saludo Manuelo, y gracias por avisar.