domingo, 13 de octubre de 2013

Memorias E2PROM embebidas

Es muy común, que en algunos de nuestros diseños sea necesario almacenar una pequeña cantidad de datos de forma que, aunque nuestro sistema se quede sin alimentación, estos datos se mantengan ahí para cuando nos sean necesarios. Esto se hace muy necesario en sistemas, por ejemplo, que están alimentados a partir de energías renovables, ya que estas, aunque puedan ir respaldadas por una batería, es posible que en algún momento no estén disponibles.
Por mi experiencia, estos datos que debemos almacenar, suelen ser datos de configuraciones que hemos seleccionado ya después de la programación, como por ejemplo la tensión de la batería que hemos conectado a un cargador de baterías,  o valores de calibración que son diferentes para cada sistema, por ejemplo si nuestro sistema acepta diferentes tipos de sensores. Otro de los usos que se les da a estas memorias no volátiles, puede ser por ejemplo el de almacenar datos, sin utilizar parte de la memoria RAM que dispone nuestro microcontrolador, como en un datalogger de cualquier magnitud.
Memorias no volátiles existen de 2 tipos básicamente, las memorias del tipo FLASH, o las memorias del tipo E2PROM. Cuando hablamos de microcontroladores, todos disponen de 2 tipos de memorias, que son la FLASH, y la RAM. En la FLASH, que como he dicho, es no volátil, almacenamos el programa, de forma que este siempre está disponible cuando nuestro sistema se alimenta, pero solo es posible escribir en ella mediante la programación mientras que en la RAM, que es una memoria volátil, se almacena el valor de las variables, por lo que se hace imposible retener un valor si la alimentación desaparece.
Vista la necesidad de introducir en nuestros diseños memorias no volátiles, lo que se nos ocurre primero es añadir una memoria E2PROM externa, y la comunicamos con el microcontrolador mediante algún protocolo serie como SPI o el I2C, pero si la cantidad de datos que queremos almacenar no es muy grande, siempre podemos utilizar la memoria E2PROM que llevan incorporados algunos microcontroladores, entre ellos la serie Arduino, además de algunos microcontroladores PIC.
Si estamos utilizando cualquier placa Arduino utilizar la memoria E2PROM interna es muy sencillo, tan solo tenemos que utilizar la librería EEPROM. Como todo lo que tiene que ver con la programación de Arduino, es muy sencilla de utilizar, y de pueden encontrar ejemplos en la página oficial de la comunidad, aquí tenéis uno para escribir, y aquí para leer. En cuanto a capacidad, las placas Arduino no escatiman en este tipo de memoria, ya que en las placas UNO contamos con 512 Bytes, mientras que para las placas MEGA 2650 contamos con 4 kBytes, lo cual es suficiente para muchas de las aplicaciones que hagamos.
En cuanto a los microcontroladores PIC, también hay un gran número de estos en los que podemos encontrar memorias EEPROM embebidas, pero si queremos un micro de gama alta, PIC32 por ejemplo, la cosa se pone muy muy dificil, sin embargo, no hay problema si queremos utilizar uno de gama media baja como PIC24 o, como en el ejemplo que os voy a mostrar, PIC18, en concreto voy a poneros un ejemplo para un PIC18F14K50. A continuación, os pongo la secuencia que hay que seguir para escribir y leer correctamente en los microcontroladores PIC.


Como veis, en cuanto a la lectura no hay problema, además que lo hace realmente rápido, ya que en un solo ciclo de reloj tenemos el dato listo para su lectura. A continuación tenéis el código C que hace la misma función que ese código de ensamblador.
char leer_eeprom(char direccion){

    EEADR = direccion;  // Escribimos la dirección
    EECON1bits.EEPGD = 0;
    EECON1bits.CFGS = 0;
    EECON1bits.RD = 1;
    return EEDATA;

}
En cuanto a la escritura es un poco más largo, pero igualmente sencillo, y aquí os pongo una función ya implementada con la que podéis escribir en las eeprom internas.
void escribir_eeprom(char direccion, char dato){

    di(); //Deshabilitamos las interrupciones

    EEADR = direccion; // Escribimos la dirección
    EEDATA = dato;  // Escribimos el dato
    EECON1bits.EEPGD = 0;
    EECON1bits.CFGS = 0;
    EECON1bits.WREN = 1;

    EECON2 = 0x55; // Secuencia de escritura
    EECON2 = 0xAA;
    EECON1bits.WR = 1;

    ei(); //Habilitamos las interrupciones

}
Espero que os sea útil esta entrada! y si tenéis alguna duda, como siempre, a los comentarios!

No hay comentarios:

Publicar un comentario