Si tu próxima aplicación para microcontroladores requiere almacenar de forma persistente configuraciones y parámetros y no deseas incluir una memoria EEPROM externa, la solución puede ser la memoria eeprom interna que incluyen la mayoría de los microcontroladores modernos.

En esta entrada compartimos nuestras rutinas para leer y escribir la memoria EEPROM interna en microcontroladores como el popular PIC16F628A, PIC16F88 y otros similares. Siendo este ultimo el que utilizaremos para esta demostración.

No es la intención explicar mucho el funcionamiento de las rutinas, ya que están basadas en lo que se encuentra en la hoja de datos, pero dejamos el proyecto completo en MPLAB X y XC8 para que quien guste pueda estudiar a fondo el tema.

Código Fuente Ejemplo memoria EEPROM Interna del PIC

Este es el archivo principal del proyecto para un PIC16F88. Puedes descargar el proyecto completo en MPLAB X más abajo.

#include <xc.h>
#include <stdio.h>

#include "Tick.h"
#include "Delay.h"
#include "UART.h"
#include "EEPROM.h"

// Fusibles de configuración MCLR (reset) Activo, Protección de lectura desactivada
// Bronw-out reset desactivado, perro guardian desactivado, Power-up timer desactivado
// Oscilador a cristal de cuarzo activo

// CONFIG1
#pragma config FOSC = INTOSCIO	// Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB0      // CCP1 Pin Selection bit (CCP1 function on RB0)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// CONFIG2
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode disabled)

xUARTHandle xSerial;
unsigned char ucCount;
unsigned long ulLastTick = 0;

/**
 Implementación de la funcionalidad principal del programa
*/
void main()
{
	//OSCCON = 0x6C;		// Para usar el oscilador interno PIC16F88 4 Mhz
	OSCCON = 0x7C;			// Para usar el oscilador interno PIC16F88 8 Mhz
	ANSEL = 0x00;			// Configuracion de canales analogicos en PIC16F88

	TRISA = 0xEF;		// Puerto A como entradas menos RA4 (led indicador)
	TRISB = 0xFF;		// Puerto B todo como entradas
	PORTA = 0;
	PORTB = 0;

	vTickInitialize();	// Iniciar el contador / temporizador del sistema
	xSerial = xUARTInitialize( E_UART_1 );

	// Abrir el puerto serie
	xUARTOpen( xSerial );
	vDelayMilis(10);
	// Mostrar mensajes iniciales, para saber que la comunicación serial funciona
	vUARTPuts( xSerial, "Entrenadora con PIC16F628rn" );
	vUARTPuts( xSerial, "Programa de prueba EEPROM Internarn" );

	// Verificamos si ya hay datos en EEPROM interna que hayamos escrito
	if( xEEPROMRead( 0x00 ) == 0xAA )
	{

		vUARTPuts( xSerial,"Encontrados datos en la EEPROM interna!!rn");
		for( ucCount = 1; ucCount <= 9; ucCount++)
		{
			// Imprimimos los números que grabamos previamente, uno en cada linea
			vUARTPuts( xSerial, "Leido: ");
			vUARTWrite( xSerial, ( xEEPROMRead( ucCount ) | 0x30 ) );
			vUARTPuts( xSerial, "rn");
		}
	}

	// Ciclo principal de nuestra aplicación
	for(;;)
	{
		// Para el parpadeo del led y verificar si el boton en RA0 esta oprimido
		if( xTickGet() - ulLastTick >= TICK_SECOND/2 )
		{
			// Cambiamos el estado lógico aplicando una operación XOR
			ulLastTick = xTickGet();
			PORTA ^= 0x10;
			// Aqui termina el código del led parpadeante :O, ahora el botón
			if( PORTAbits.RA0 )
			{
				// Incremetar un contador por cada medio segundo que RA0 esta presionado
				ucCount ++;
				if( ucCount > 10 )	// Despues de 5 segundos ejecutar la escritura en EEPROM interna
				{
					vUARTPuts( xSerial,"Escribiendo datos a la EEPROM!rn");
					for( ucCount = 1; ucCount <= 9; ucCount++)
					{
						vUARTPuts( xSerial, "Escribe: ");
						// La llamada a esta función es la que realmente realiza la escritura
						vEEPROMWrite( ucCount, ucCount );
						// Conversión simple de número binario a caracter ASCII para poder
						// mostrar el número en la terminal (ver valores binarios en tabla ASCII)
						vUARTWrite( xSerial, ( ucCount | 0x30 ) );
						vUARTPuts( xSerial, "rn");
					}
					// El byte 0xAA en la posición 0 indica que ya escribimos datps
					// en la memoria EEPROM del PIC
					vEEPROMWrite( 0xAA, 0x00 );
					ucCount = 0;
				}
			}
			else	// Si el boton se suelta mantenemos ucCount en 0
			{
				ucCount = 0;
			}
		}
	}
}

/**
 Implementación del vector de interrupción (único)
*/
void interrupt isr( void )
{
	// Actualizar el conteo del tiempo
	vTickUpdater();
	// Otras interrupciones
}

 ¿Que hace el programa?

Se trata solamente de una demostración que hace 3 cosas muy básicas.

  • Al arrancar, el programa muestra un mensaje en el puerto serie a 9600 bps y verifica si ya escribimos algo en la EEPROM interna y si es así imprime el contenido de la memoria EEPROM.
  • Verifica constantemente si oprimimos por más de 5 segundos un botón conectado al pin RA0 y si es así escribe datos en la EEPROM interna
  • Hace parpadear un led conectado al pin RA4

El uso del programa es más o menos así: Después de grabar el programa, la EEPROM interna del PIC se encontrará en blanco, por lo que no se mostrará el mensaje inicial que informa que se encontraron datos. Mientras el led conectado en RA4 parpadea, oprimiremos el botón conectado en RA0 para iniciar la secuencia de grabación de EEPROM. El programa mostrará lo que esta grabando a través del puerto serie. Al reiniciar el PIC o retirarle la alimentación, debemos ver el mensaje al arrancar de que se han encontrado datos en la memoria EEPROM.

La siguiente captura muestra la salida del puerto serial de nuestro ejemplo:

Funcionamiento del programa de prueba para la EEPROM interna en PICs de la familia PIC16F.

Funcionamiento del programa de prueba para la EEPROM interna en PICs de la familia PIC16F.

Al leer la memoria del PIC con la herramienta del PICKit 2 vemos que aparecen los datos que nuestro programa grabó:

Captura de pantalla de la herramienta del PICKit 2, se muestran los datos grabados en la EEPROM por nuestro programa.

 Descarga del proyecto para MPLAB X

Descarga el código fuente, incluyendo el código fuente de las rutinas de acceso a la EEPROM:

 

Agradeceríamos tus comentarios sobre el código y sobre el funcionamiento de este proyecto.