TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Agustina en 18 de Mayo de 2007, 01:47:51

Título: Escribir variables int32 en eeprom externa
Publicado por: Agustina en 18 de Mayo de 2007, 01:47:51
Hola! :g) he estado trabajando con una eeprom externa por i2c y se me ha presentado un problema, trato de escribir una variable int32 en la eeprom, pero luego al leerla, lee cualquier otro numero  :? les adjunto el programa


/////////////////////////////Funcion para escribir float en eeprom///////////////////////////
WRITE_FLOAT_EXT_EEPROM(long int n, long data) {

   int i;

   for (i = 0; i < 4; i++)

     write_ext_eeprom(i + n, *(&data + i) ) ;

}


/////////////////////////////Funcion para leer float en eeprom///////////////////////////

long READ_FLOAT_EXT_EEPROM(long int n) {

   int i;

   long data;

   for (i = 0; i < 4; i++)

     *(&data + i) = read_ext_eeprom(i + n);

   return(data);

}

luego dentro del main para escribir y leer la variable coloco esto:


write_float_ext_eeprom(218,factor_int);
lcd_putc("\fleyendo...");
delay_ms(1000);
factor_int=read_float_ext_eeprom(218);
printf(lcd_putc,"\f%8.7w",factor_int);
delay_ms(1000);

me podrian aconsejar a ver si puedo detectar el problema?
Muchas gracias!!  :mrgreen: :mrgreen:
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: Nocturno en 18 de Mayo de 2007, 01:52:45
¿Cómo tienes declarada la variable factor_int?
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: MGLSOFT en 18 de Mayo de 2007, 09:56:44
Ademas existe la posicion 218 en esa memoria?? :mrgreen: :mrgreen:
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: RedPic en 18 de Mayo de 2007, 10:13:27
Independiente de todo los demás: Una variable declarada como Long es de 16 bits (int16) no de 32 bits (int32) luego data solo tiene dos bytes de largo y tus funciones estan escribiendo y leyendo cuatro  :shock: por lo tanto los resultados no pueden ser mas que aleatorios y cualquier parecido con la realidad es mera coincidencia.   :D :D

Declara las variables de 32 bits como int32 y vuelve a probar.  :mrgreen:

Un saludo.

PD1: Del manual de CCS ... By default the compiler treats SHORT as one bit, INT as 8 bits and LONG as 16 bits.
PD2: Tambien puedes redeclarar tus tipos de variables con #TYPE SHORT=8, INT=16, LONG=32
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: MGLSOFT en 18 de Mayo de 2007, 11:37:37
Hay una libreria de CCS que esta hecha para hacer este trabajito.
Se llama External_EEprom.c

Alli las funciones son algo diferentes a las que escribiste.
Código: [Seleccionar]
// Purpose:    Write a floating point number to external eeprom
// Inputs:     1) An eeprom address. Four eeprom locations will be used.
//             2) The floating point number to write to external eeprom
// Outputs:    None
void write_float_ext_eeprom(EEPROM_ADDRESS address, float data)
{
   int8 i;

   for(i = 0; i < 4; ++i)
   {
     write_ext_eeprom(address + i, *(&data + i));
   }
}


// Purpose:    Read a floating point number from external eeprom
// Inputs:     An eeprom address
// Outputs:    The floating point number read from the external eeprom
float read_float_ext_eeprom(EEPROM_ADDRESS address)
{
   int8 i;
   float data;

   for(i = 0; i < 4; ++i)
   {
     *(&data + i) = read_ext_eeprom(address + i);
   }

   return data;
}

RedPic tiene razon, como siempre... :mrgreen: :mrgreen: :mrgreen:
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: Agustina en 18 de Mayo de 2007, 15:17:07
muchas gracias por las respustas!!!  :g)  ahora probare para ver si todo funciona bien  :o
El problema de las variables LONG lo resolvi luego de dejar este post  :P pero el problema seguia igual, asique probaré con las demás sugerencias!!!

Muchisisisisisimas gracias!!  :mrgreen: en unas horas les cuento si todo salió bien!
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: Agustina en 19 de Mayo de 2007, 14:44:33
 :( no se soluciono, ya no se que hacer... uso las funciones de external_eeprom.c y tampoco... factor int es un int32, cuando lo incremento y lo muestra en el display, muestra los valores que ingreso por ejemplo 3079843 que es un int32, pero cuando lo guardo en la eeprom al leerlo lee un valor que nunca excede los 255 (int8) ... no entiendo que estoy haciendo mal  :?
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: vszener en 19 de Mayo de 2007, 15:18:13
¿Tu eeprom puede soportar 32-bits?es decir, de que tamaño son sus registros...


Suerte!!! ;)
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: MGLSOFT en 20 de Mayo de 2007, 12:52:05
Todos los datos son de 8 bits en estas rutinas, solo que cada una ocupa 4 posiciones de 8 bits indexadas a partir de la posicion inicial, tanto para la escritura como para la lectura funciona asi, lee las rutinas y veras que es asi.

 :mrgreen: :mrgreen:
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: Agustina en 28 de Mayo de 2007, 19:28:09
no logre hacer funcionar lasrutinas que provee CCS para el manejo de enteros de 32 bits... asique cree una que se entiende un poco mas y anda a la perfeccion, se las dejo por si alguien tiene el mismo problema!  :g)


void write_int32_ext_eeprom(int16 direccion, int32 dato)
   {
   int dato_0,dato_1,dato_2,dato_3;

   dato_3 = make8(dato,3);   //MSB
   dato_2 = make8(dato,2); 
   dato_1 = make8(dato,1); 
   dato_0 = make8(dato,0); 

   write_ext_eeprom(direccion,dato_3);
   direccion++;
   write_ext_eeprom(direccion,dato_2);
   direccion++;
   write_ext_eeprom(direccion,dato_1);
   direccion++;
   write_ext_eeprom(direccion,dato_0);
   return;
   }


int32 read_int32_ext_eeprom(int16 direccion)
   {
   int32 dato;
   int dato_0,dato_1,dato_2,dato_3;
   
   dato_3=read_ext_eeprom(direccion);
   direccion++;
   dato_2=read_ext_eeprom(direccion);
   direccion++;
   dato_1=read_ext_eeprom(direccion);
   direccion++;
   dato_0=read_ext_eeprom(direccion);

   dato=make32(dato_3,dato_2,dato_1,dato_0);
   return(dato);
   }
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: jeremylf en 23 de Agosto de 2008, 04:33:50
Tengo el mismo problema yo en estos momentos pero con las funcion para escribir y leer variables float =S Alguien podria asegurar que las funciones del external_eeprom.c del ccs funcionan correctamente? y sino, mostrar alguna otra forma de poder leer/escribir float n una eeprom?

Gracias.
Un saludo.
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: RICHI777 en 23 de Agosto de 2008, 16:09:43
Hola, suponiendo que tengamos funciónes que escriban y lean desde/hacia EEPROM a nivel byte se podrian hacer dos funciones que sirvan para cualquier tipo de dato, doy el ejemplo para un int32 independiente del largo que tenga.
Código: [Seleccionar]
void SaveInt32ToEEprom( int16 Address, int32 Data )
{
  /* Se instancia un buffer de igual tamaño del tipo da dato, no me debe importar el tamaño, el compilador lo resolvera en tiempo de compilacion */
  int8 MyBuffer[sizeof(int32)]; 
  int8 Index;

  /* Copio el Dato al buffer */
  memcpy( Buffer, &Data, sizeof( int32 ));

  /* Salvo en EEPROM */
  for ( Index = 0; Index < sizeof( int32 ); Index ++ )
  {
      write_ext_eeprom(Address ++, Buffer[Index]);
  }
}

int32 GetInt32FromEEprom( int16 Address )
{
  /* Se instancia un buffer de igual tamaño del tipo da dato, no me debe importar el tamaño, el compilador lo resolvera en tiempo de compilacion */
  int8 MyBuffer[sizeof(int32)]; 
  int32 Temp;
  int8 Index;

  /* Leeo de EEPROM */
  for ( Index = 0; Index < sizeof( int32 ); Index ++ )
  {
      Buffer[Index] = read_ext_eeprom(Address ++);
  }

  /* Copio el Dato al buffer */
  memcpy( &Temp, Buffer, sizeof( int32 ));

  return( Temp );
}

La función se puede adaptar a cualquier tipo de dato por ejemplo float, reemplazando los int32 por float. Cabe aclarar que estas funciones estan escritas en ANSI C, lo que es necesario para su implementación es que el compilador soporte la función de la RTL memcpy y el operador sizeof

Saludos !
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: MLO__ en 23 de Agosto de 2008, 16:11:54
Hola.

Las funciones si funcionan y muy bien  :-/, claro que a 8 bits. Si quieres guardar un float, debes pasarlo a string y guardarlo de esa manera en la memoria, por ejemplo, si quieres guardar 2.34, lo pasas a {'2', '.', '3', '4'} y ocuparias 4 registros de la memoria. Para leerlo, simple  :mrgreen: , pasas el string a float y ya.

Saludos.
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: firepic en 25 de Agosto de 2008, 13:22:51
Saludos a todos!

Miguel, respeto tu experiencia y opiniones, muy maduras siempre. Ahora bien, imagínate un número float, digamos -12.038,56... Eso llevado a string serán mucho más de 4 registros de memoria, cierto? Por eso es que me parece un poco ineficiente ese método, a menos que estés seguro de que los valores siempre serán pequeños. De lo contrario, creo que lo mejor es usar apuntadores para guardar los 4 registros que componen la variable float en la eeprom externa, como lo que propone Richi.
 
Ahora bien, Jeremy, CCS provee una librería llamada FLOATEE que es justamente para hacer ese trabajito. Y funciona a la perfección!
Si mal no recuerdo, las instrucciones son: write_float_ext_eeprom y read_float_ext_eeprom... usando esas no tendrás problemas. Solo debes cuidar bien la dirección de la memoria a escribir, debes ir incrementando de cuatro en cuatro de un dato a otro, razón obvia.

Ok nos leemos!  :mrgreen:
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: MLO__ en 25 de Agosto de 2008, 13:56:16
Hola.

Tranquilo Javier  :x  :x  :x jajaja ...... no sabia que habia esa libreria .. hoy, gracias a ti, la vengo a ver!!!!  :P normalmente no trabajo con numeros cuya parte entera sea grande y con mas de 2 decimales (por lo de la resolucion, no puedo asegurarla!!!), pero ahora que la vi, le voy a dar muuucho uso!!!

Saludos
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: jeremylf en 27 de Agosto de 2008, 00:29:31
Hola. Firepic la libreria q intente usar para leer/escribir float es la external_eeprom.c del CCS 4.023, siendo estas las funciones:

Código: [Seleccionar]
// Purpose:    Write a floating point number to external eeprom
// Inputs:     1) An eeprom address. Four eeprom locations will be used.
//             2) The floating point number to write to external eeprom
// Outputs:    None
void write_float_ext_eeprom(EEPROM_ADDRESS address, float data)
{
   int8 i;

   for(i = 0; i < 4; ++i)
   {
     write_ext_eeprom(address + i, *(&data + i));
   }
}

Código: [Seleccionar]
// Purpose:    Read a floating point number from external eeprom
// Inputs:     An eeprom address
// Outputs:    The floating point number read from the external eeprom
float read_float_ext_eeprom(EEPROM_ADDRESS address)
{
   int8 i;
   float data;

   for(i = 0; i < 4; ++i)
   {
     *(&data + i) = read_ext_eeprom(address + i);
   }

   return data;
}

Habiendo un error (creo) en el compilador porque revisando con el MPLAB SIM cuando hago esto: (&data + i), ocea que si le sumo por ejemplo + 1 a la direcion de "data", el compilador lo que hace es sumarle 4 bytes mas porque asi lo entendiera y creo que eso hacia que me devolviera variables erroneas, cosa mal porque tiene que seguir leyendo en los otros 3 bytes del valor flotante.

Bueno, ahora uso lo que propuso RICHI777 que va de maravilla. No conocia esa funcion memcpy que al parecer hace lo mismo pero de manera correcta, gracias.
Cuanto tenga mas tiempo probare a mas detalle si el problema es con el compilador u otra cosa.

Gracias a todos.
Un saludo.
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: RICHI777 en 27 de Agosto de 2008, 12:23:22
Hola, dependiendo del compilador utilizado la función que detalla jeremylf adolece de 2 problemas:

Problema 1
Código: [Seleccionar]
for(i = 0; i < 4; ++i)
De esta manera se asume que siempre un float ocupara 4 bytes, y esto puede no ser siempre verdad, si por alguna razon se cambia el tamaño de la representación del float deberiamos tener que modificar la función.
De la sgte manera me independizo del tamaño
Código: [Seleccionar]
for(i = 0; i < sizeof( float ); ++i)

Problema2

Código: [Seleccionar]
write_ext_eeprom(address + i, *(&data + i));

Según la aritmetica de punteros cuando se opera se utiliza el tamaño del mismo salvo que exista cast especifico, por eso cuando &data + 1 el puntero pasa a tener +4, porque un float ocupa 4 bytes, lo mismo pasaria si haria (&data ++ ).
La correcta escritura de esta operación seria esta:

Código: [Seleccionar]
write_ext_eeprom(address + i, *((( int8 * )&data ) + i));

De esta manera el puntero intermedio es tratado como un int8 y solo es incrementado en unidades de a uno.

Saludos !
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: jeremylf en 27 de Agosto de 2008, 18:54:35
Por lo primero, no creo que cambien el formato para los float, que utiliza tb microchip, aunq lei q habia un tal IEE... pero igual creo que ocupaba 4 bytes  :mrgreen:

Por lo otro... habra que darles un jalon de orejas a los de CCS entonces xD!

Muchas gracias RICHI777 por la aclaracion.
Salu2.
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: firepic en 27 de Agosto de 2008, 19:56:21
El formato para los float en CCS siempre es el mismo, y ocupa 32bits, o sea 4 bytes. Jeremy está en lo correcto.
Y pues debe ser un error de ese compilador. Yo uso el 4.057, y está tal cual lo coloca Richi. Debieron haberlo corregido con esa versión.
Como te digo, a mi me funcionó de maravilla.  :lol:
Saludos!  :mrgreen:
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: RICHI777 en 27 de Agosto de 2008, 23:40:04
Hola, con respecto al primer punto en si es una sugerencia mas que un error, es mas prolijo escribirlo de la forma que denote. Igual gracias por las aclaraciones

Saludos !
Título: Re: Escribir variables int32 en eeprom externa
Publicado por: RedPic en 03 de Septiembre de 2008, 09:58:57
Hola, dependiendo del compilador utilizado la función que detalla jeremylf adolece de 2 problemas:
...

Código: [Seleccionar]
for(i = 0; i < sizeof( float ); ++i)

Código: [Seleccionar]
write_ext_eeprom(address + i, *((( int8 * )&data ) + i));

De esta manera el puntero intermedio es tratado como un int8 y solo es incrementado en unidades de a uno.
Saludos !

Muy bien, Richi777. Me encanta tu planteamiento/propuesta. Es elegante, canónico y clarificador, válido para distintos C´s y tipos de variables. Me gusta.  :mrgreen: