Autor Tema: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes  (Leído 12344 veces)

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

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
 :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. 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:


 
La distribución física de los pines en el Chip es la siguiente:


  
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)
  


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



Recursos:
  
Datasheet del chip 24AA1025 (PDF 357 Kb)
  
Driver y Software:
  

 
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 y
El Driver Microchip 24AA512 512k I2C EEPROM de UFAnders
 
Pero dejémonos de mas dilaciones innecesarias y entremos en faena con nuestro Driver I2C para memorias EEPROM de gran tamaño:


  
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:
 

 
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:
 
 

 


  

 
Ea, ahí queda eso. Mañana más.   :mrgreen: :-/ :mrgreen:

Nota: El driver en CCS C definitivo está a partir de este post (Enero 2008)
« Última modificación: 26 de Junio de 2009, 18:15:10 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado samshiel_pic

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 773
    • Electrónica·Ingenia
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #1 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 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

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #2 en: 15 de Octubre de 2006, 15:34:38 »
Si amigo Samshiel_pic, para una cosa parecida lo necesito yo. :mrgreen:

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado samshiel_pic

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 773
    • Electrónica·Ingenia
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #3 en: 15 de Octubre de 2006, 15:50:20 »
Espero noticias sobre ello amigo :P

Desconectado vinny

  • PIC10
  • *
  • Mensajes: 27
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #4 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
Solo existen dos cosas infinitas, el universo y la estupidez humana, de lo primero no estoy seguro...

Desconectado vinny

  • PIC10
  • *
  • Mensajes: 27
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #5 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



Solo existen dos cosas infinitas, el universo y la estupidez humana, de lo primero no estoy seguro...

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #6 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.






Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado vinny

  • PIC10
  • *
  • Mensajes: 27
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #7 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á.
Solo existen dos cosas infinitas, el universo y la estupidez humana, de lo primero no estoy seguro...

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #8 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

« Última modificación: 21 de Diciembre de 2006, 02:10:51 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado vinny

  • PIC10
  • *
  • Mensajes: 27
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #9 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
Solo existen dos cosas infinitas, el universo y la estupidez humana, de lo primero no estoy seguro...

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #10 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
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 17493
    • MicroPIC
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #11 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:
Un saludo desde Sevilla, España.
Visita MicroPIC                                                                                        ɔ!doɹɔ!ɯ ɐʇ!s!ʌ

Desconectado pikman

  • Moderadores
  • PIC24F
  • *****
  • Mensajes: 674
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #12 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.

« Última modificación: 03 de Enero de 2007, 11:00:14 por pikman »
saludos
PikMan

Desconectado LordLafebre

  • Moderador Global
  • DsPIC30
  • *****
  • Mensajes: 3529
    • Micros & micros
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #13 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:

Desconectado Sispic

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1414
    • winpic800
Re: Circuito y Driver C para 4 Memorias EEPROM 24AA1025 con un total de 512 Kbytes
« Respuesta #14 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
« Última modificación: 03 de Enero de 2007, 14:01:13 por Sispic »