Guardar un dato de 16 bits en la eeprom de un 16f876a

Dr. Zoidberg

Well-known-Papá Pitufo
Yo usaria algo mas simple:
Código:
typedef union {
   int16 dato;
   unsigned char b[2];
} int2bytes;
Con esa union es muy simple la transformacion:
Código:
...
int2bytes x;

x.dato = dato_de_16_bits;
dato_bajo_de_8_bits = x.b[0];
dato_alto_de_8_bits = x.b[1];

La conversion inversa es simple de imaginar...
 
Última edición:
Muchas gracias a ambos por sus respuestas, la verdad un foro genial, al igual que la coordialidad de sus miembros, en c nunca habia programado, en delphi que utiliza pascal si tengo años de experiencia y me ayuda a comprender el codigo c proque tiene sus similitudes y bueno la logica de programacion es mas menos la misma en todos los lenguajes. Automatizaba procesos con software sobre windows, controlando por puertos usb o lpt1 o com. ahora estoy en el mundo de los pic y mas recientemente en con las placas arduino que me ahoran todo el lio de ensamblar el circuito. Gracias de nuevo y de seguro estare por aca con mas dudas y espero que alguna que otra vez tambien yo pueda aportar algo a quien lo necesite.
 
Usa la librería incluida con el IDE. "internal_eeprom.c"
Tiene las rutinas "write_float_eeprom" y "read_float_eeprom"
No recuerdo si se usan 3 o 4 bytes, así que debes tener cuidado con eso para no sobreescribir locaciones.

Hola D@rbytes, estado probando lo que dices y va de lujo, al principio me creò problemas por que no me di cuenta de poner la libreria "internal_eeprom.c", una vez puesta todo perfecto.

Una pregunta, quiero probar para contar las vueltas de un tacometroy guardarlas por si hay corte de tension, en float usa 4 direcciones, voy a usar un int16 que es mas que suficiente, he leido por algun sitio que no hay que abusar de la eeprom a la hora de estar guardando datos, como solo va ser en momentos puntuales, es correcto que ponga "write_int16_eeprom(direccion,variable);" dentro le la interrupcion?

Código:
#int_timer1
   void timer1_isr(void){
     vueltas=get_timer0();
      rpm=vueltas*2;
       write_int16_eeprom(6,rpm);
       set_timer0(0);
        set_timer1(3036); 
        }

o no es un problema de mayor importancia?.
 
Hola, las celdas EEPROMs, tienen una limitada cantidad de ciclos de escritura. Entonces en tú caso, a la hora de almacenar el valor, tienes que detectar el momento en que se produce la falta de alimentación. Y ahí, en esos pocos milisegundos que haya de tiempo, hasta que la tensión de fuente decae, almacenar en los registros EEPROM.
 

D@rkbytes

Moderador
Una pregunta, quiero probar para contar las vueltas de un tacómetro y guardarlas por si hay corte de tensión.
En float se usan 4 direcciones, voy a usar un int16 que es más que suficiente.
He leido por algun sitio que no hay que abusar de la eeprom a la hora de estar guardando datos.
Como solo va ser en momentos puntuales, ¿es correcto que ponga "write_int16_eeprom(direccion,variable);" dentro le la interrupción?
¿O no es un problema de mayor importancia?
Es preferible usar banderas y posteriormente las verifiques.
En algunos casos no pasa nada si se introducen rutinas de ese tipo en el servicio de interrupción, pero en otros casos sí pueden afectar.
Como quiera, el compilador se da cuenta de ello y deshabilita la interrupción hasta que se ejecute el código interno.
Cuando eso sucede lo podrás ver en el log de compilación como una advertencia.

Ahora, la mayoría de las EEPROMS internas de los PIC's, si no es que todos, soportan alrededor de un millón de lecturas o escrituras.
Alguna hoja de datos dijo:
• 1,000,000 erase/write cycle Data EEPROM memory typical
• Data EEPROM Retention > 40 years
Así que con ese dato puedes saber cuánto podría tener de vida la EEPROM.
Que escribiéndola constantemente como en el código que expones, no sería por mucho tiempo.

Es mejor realizar lo que menciona Gudino, si no quieres que la EEPROM se deteriore pronto.
Por aquí en alguno de los foros subí un ejemplo de cómo hacerlo.
No recuerdo en cual, ni tampoco en qué lenguaje escribí el programa.
Pero dale una leída al registro PCON y te podrás dar una idea de la implementación.
 
Hare lo que dice gudino, para ello me basare en el ejemplo que pusiste D@rbytes en un post, para ello tambien cambiare algunos condesadores, sobretodo el de filtrado que alimenta el micro, hay pondre uno de 4700uf.

Gracias a los dos.
 
Recomendación, es preferible detectar el shut down, antes del regulador que alimenta al microcontrolador.
Pues si lo haces a la salida del mismo, sólo podrás detectarlo cuando dicho regulador deje de hacer lo que mejor hace,:D y puede ser tarde... y el micro puede entrar en mal funcionamiento, dependiendo de cómo esté configurado el fuse BOR. Sin ir más lejos, al detectar en la entrada del regulador cómo mencioné, recuerda que esa tensión de muestra, no supere a la de alimentación del controlador, yo suelo utilizar una simple resistencia, asociado a un zener de 5V1.(o la tensión de VDD) y un pequeño condensador de 100nF cómo filtro de algún ruido que pueda colarse a la entrada.
 
Última edición:
Código:
  set_adc_channel(3);           // Activar el canal 3
      delay_us(50);
      
      adc_corte = read_adc();       // Leer el canal 3 para sensar corte eléctrico.
      
      if(adc_corte <= 850)          // Si la lectura del canal 3 es menor a 850...
              {
         // Se escriben las temperaturas seleccionadas en la eeprom interna.
         write_eeprom(0,temp_min);
         delay_ms(10);
         write_eeprom(1,temp_max);
         // Se avisa sobre el suceso.
         lcd_putc("\f     !AVISO!");
         lcd_putc("\n CORTE ELECTRICO ");
         delay_ms(5000);
            }

Esto esta sacado de D@rbytes, pero en su ejemplo la alimentacion la toma despues del 7805, que es donde tiene puesto un electrolitico de 4700uf, tu hablas de cojerla antes del regulador y con una resistencia limitadora mas el zener de 5.1 mandarlo a la entrada analogica.

Por lo que veo, creo que las dos opciones son validas, no crees?

Una pregunta, uso el 16F877A y todas las entradas del puertoA analogico las tengo ocupadas, que otra solucion podria usar para tener la referencia de la entrada analogica?, es por no restructurar las entradas.
 
Última edición:

D@rkbytes

Moderador
Esto esta sacado de D@rbytes, pero en su ejemplo la alimentación la toma después del 7805, que es donde tiene puesto un electrolítico de 4700 uF.
Tú hablas de cojerla antes del regulador y con una resistencia limitadora mas el zener de 5.1 mandarlo a la entrada analógica.
Me parece que no leíste sobre las consideraciones a tomar sobre ese circuito.
Para lograr que el circuito funcione correctamente se deben tomar algunas consideraciones.
1.- Separar la alimentación del PIC y colocar un capacitor de 4700uF en VDD para mantener constante por algún tiempo la alimentación del mismo y así poder ejecutar las tareas de detección.
También se puede colocar un sistema con batería recargable para mantener siempre alimentado al PIC.
2.- De preferencia tomar la muestra de tensión a través de un diodo antes del filtraje del voltaje.
3.- Espero que funcione.
 
Arriba