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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #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:
Al leer la memoria del PIC con la herramienta del PICKit 2 vemos que aparecen los datos que nuestro programa grabó:

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.