Como usar la EEPROM de los PICs

Estado
Cerrado para nuevas respuestas.
Usando la EEPROM de los PICs (ejemplo PIC 16x84)

Hemos visto que en muchos de los post y discusiones de este foro, hablamos de guardar los datos en la memoria EEPROM de los microcontroladores.

En realidad no sabemos hasta donde llega el conocimiento de todos los que leemos esos escritos, por lo tanto trataremos de hacer una pequeña introducción de cómo proceder para usar la memoria EEPROM.

Entonces, este mini tutorial está orientado a aquellos que no conocen o nuncan han intentado usar esta memoria.

Muchas veces (si no la mayoría de ellas) subutilizamos el MP (microprocesadores) basándonos en el software de control desarrollado en nuestras PC para guardar y leer los datos necesarios para el correcto funcionamiento de nuestras interfaces y circuitos de control, en lugar de emplear a fondo las facilidades que nos prestan.

Existen muchas ventajas en guardar los datos en la memoria no volátil del MP. La más inmediata y evidente es disponer en forma instantánea de las condiciones iniciales o de arranque para el funcionamiento de la electrónica de control.

Por ejemplo, imagínense que hemos diseñado un circuito que utiliza un motor paso a paso para colocar en determinado lugar una banda transportadora. Sabemos que el motor deberá moverse desde 0 (inicio de la banda) hasta X pasos (final de la banda). Dentro de la memoria EEPROM podríamos almacenar el valor de X (numero de pasos totales para recorrer la banda) y el valor de Y (lugar o número de pasos en donde se detuvo por última vez el motor). De esta forma, el circuito podría usar su “memoria” para conocer estos datos al encenderlo en lugar de esperar que algún otro proceso externo se lo informe. Otros datos que pudiéramos guardar serían por ejemplo, el valor de corrección de “backslash” o de movimiento inercial de la banda para corregir ese error acumulativo.

Para explicar como usar la EEPROM, vamos a basarnos en nuestro PIC de pruebas que es el ya famoso 16x84. Para utilizar cualquier otro, haremos uso de las datasheets para conocer la equivalencia de los comandos, el tamaño de la EEPROM y sus direcciones de inicio y final. En el caso de 16x84 tenemos los siguientes datos:

Tamaño de la EEPROM: 64 bytes - 8 Bits por byte
Dirección de Inicio: 0h
Dirección Final: 3Fh


Para acceder a esos 64 bytes usamos un direccionamiento indirecto. Esto quiere decir que la DIRECCIÓN específica de la memoria EEPROM que nos interesa (de los 64 disponibles) estará almacenada en un registro determinado y por consiguiente, para que el programa del MP sepa donde leer o grabar tendremos que buscarlo en ese registro específico.

Este registro junto con otros cuatro que sirven para controlar todo el proceso de lectura y escritura, son los siguientes:

EEADR
EEDATA
EECON1
EECON2


1) EEADR contiene la dirección o posición de la memoria EEPROM que queremos acceder bien sea para leerla o escribirla. Como este registro es un BYTE de 8 Bits, pudiéramos entonces representar 256 distintos valores sin embargo solo necesitamos 64 de ellos para acceder a toda la memoria por lo que, los bit 6 y 7 no se usan y deberán ser siempre cero (recuerden que los 8 bits los numeramos desde el 0 al 7).

2) EEDATA va a contener como su nombre lo indica, el dato leido o el que deseamos guardar.

3) La misión de EECON1 es controlar los procesos de escritura/lectura de la memoria. De sus 8 bits disponibles solo se usan los 5 de menos peso. Estos bits son:

a. Bit0: RD de “Read Data”, se pone a 1 cuando se va a realizar un ciclo de LECTURA desde la EEPROM, y vuelve automáticamente a 0 cuando se temina ese proceso.

b. Bit 1: WR de “Write Data”, se pone a 1 cuando se va a realizar un ciclo de ESCRITURA hacia la EEPROM, y vuelve automáticamente a 0 cuando se temina ese proceso.

c. Bit 2: WREN de “Write Register ENable”. Si está a 1 PERMITE el proceso de escritura hacia la EEPROM y si está a 0, no lo permite.

d. Bit 3: WRERR de “Write Register ERRor”. Se va a 1 cuando un proceso de ESCRITURA no se realizó correctamente y a 0 en caso contrario.

e. Bit 4: EEIF de “EEprom Interrupt Finalization”. Al colocarse a 1, indica que la operación de ESCRITURA a finalizado con éxito. Si se quiere colocarla a 0, deberá hacerse por programa.

4) EECON2 no está físicamente implementado y es empleado como un dspositivo de seguridad durante el proceso de escritura de la EEPROM. Si se lee, todos sus bits estarán a 0.

Un ciclo de escritura de una localidad de memoria de la EEPROM tarda aproximadamente para estos MP con cristales de 4 MHz, unos 10 ms. Este tiempo es muy largo comparado con la velocidad del MP y por esta razón se hacen tantos esfuerzos en controlar su escritura y lectura.

Leer los datos de la EEPROM:

Según lo que vimos anteriormente, para leer los datos de la EEPROM deberemos hacer lo siguiente:

1) Cargar la dirección que deseamos leer en EEADR
2) Poner a 1 el Bit RD del registro EECON1 indicándole al MP que lea la dirección
3) Y por último transferir al acumulador o al literal deseado el dato leído desde EEDATA

El código típico sería así (Recuerden que debemos de haber incluido el archivo 16F84A.INC donde se definen los registros del PIC). La variable DIRE debimos haberla declarado al comienzo del programa.

Código:
bcf          ESTADO,RP0	;Seleccionamos el Banco 0
movlw	     DIRE			;Ponemos en W la dirección que vamos a leer
movwf	     EEADR		;y pasamos W al registro EEADR, definiendo la dirección a leer
bsf		ESTADO,rp0		; Seleccionamos el Banco 1
bsf		EECON1,RD		;Hacemos la lectura colocando RD a 1 
bcf		ESTADO,RP0	;y regresamos al Banco 0
movf	      EEDATA,W		;para finalmente rescatar el dato desde EEDATA hacia W

Esta es una codificación básica que puede servir de modelo de arranque para sus diseños.

Escribir los datos en la EEPROM:

Anteriormente dijimos que EECON2 no estaba implementado en forma física y que si lo leíamos obtendríamos 0 pero, cumple funciones de control sobre la escritura que si deberemos considerar.

Para esto, usaremos dos valores específicos, el 55h y el AAh.

Dado el tiempo que tarda el proceso de escritura comparado con el tiempo de ejecución del MP, estos dos valores permitirán al MP realizar acciones de sincronismo y control en el proceso de escritura de la EEPROM, así es que el código deberá tener un par de instrucciones de escrituras en EECON2 que parecieran no tener sentido pero que siempre deberemos usar, al menos en esta gama de PICs.

El código sería el siguiente:
Las variables DIRE y ESCR la debimos de haber declarado al comienzo del programa.


Código:
bcf		STATUS,RP0		;Seleccionamos Banco 0
movlw		DIRE			;Ponemos en W la dirección que vamos a escribir
movwf		EEADR		;y la guardamos en EEADR
movlw		ESCR			onemos ahora el dato a escribir en W
movwf		EEDATA		;y lo guardamos en EEDATA

bsf		STATUS,RP0		;Seleccionamos Banco 1
bsf 		EECON1,WREN 	;Colocamos el permiso de escritura (WREN) en EECON1 a 1
					;Aquí da inicio la secuencia de escritura

movlw		0x55 h			;Inicio de las intrucciones para EECON2
movwf		EECON2
movlw		0xAA h		
movwf		EECON2		;Fin de las intrucciones para EECON2

bsf		EECON1,WR		;Comienza la escritura propiamente dicha.

Cuando se complete todo el proceso de escritura, el Bit WR se pondrá a 0 automáticamente y el señalizador de interrupciones EEIF pasará a valer 1 (y allí se quedará hasta que lo coloquemos a 0 por programa).

Si se quiere realizar un proceso simple de verificación de escritura adicional, podemos restar el dato que hemos escrito al valor actual del registro EEDATA. Si no hubo errores entonces esta resta debe dar 0 y por lo tanto el bit Z (cero) del registro de ESTADO se colocará a uno indicando esta condición, lo que nos servirá de bandera de comprobación.

Seguramente habrán diferencias notables en el manejo de lectura/escritura de otros modelos de PIC y de otra marca de microcontroladores pero su base de funcionamiento es prácticamente la misma.

Deberán tener en cuenta que el proceso de escritura de un byte, borra automáticamente la posición de memoria y luego escribe el dato es decir, borra antes de escribir, así es que tendrán que rescatar el dato anterior antes de su escritura si lo quieren utilizar para algo.

Las memorias EEPROM resisten hasta un millón de ciclos de Lectura/Escritura y además pueden almacenar sus datos en forma contínua sin degradación por alrededor de 40 años.

Para los que no lo saben, EEPROM significa: Electrically Erasable Programmable Read Only Memory, que en castellano podría ser algo como: Memoria Programable de Solo Lectura Borrable Eléctricamente (MPSLBE ?????:rolleyes:).

Espero les sea de utilidad esta explicación y comiencen a sacarle más provecho a sus MC.

Saludos,
Marcelo.
 
ooooooo ase tiempo que queria utilizar la eeprom pero no entiendo como funciona aun :p
vamos a practicar y para ver cuanto entendi
siempre q uso algun pic lo apago y se borra la info de algun proceso o datos del trabajo xP
pero ahora podre realizar un proyecto mejor!
dommo arigato
 
realize unas pequeñas pruebas y me funcionaron! :aplauso:(y)

ahora podre mejorar mas aun mis proyecto lo que no me gusto fue la rutina muy larga :enfadado: me desconfigura lo que es transmicion de datos
ahora estos datos se pueden leer con el pc
yo utilizo el icprog para grabar los datos al PIC, cuando leo el PIC no me sale en ningun lado los datos :unsure::eek:


muchas gracias
saludos
 
Última edición:
Bueno yo como necesito tener una constante estoy tratando de ponerla en la EEPROM y leerla pero no me funciona. Esto es lo q tengo escrito:

#include"p16F877.INC"
list p=16F877

NUM1 EQU 0X16F
NUM2 EQU 0X1EF
SUMA EQU 0X72
AUX EQU 0X20

ORG 0X00
BCF STATUS,RP0
MOVLW 0X00
MOVWF EEADR
BSF STATUS,RP0
BSF EECON1,RD
BCF STATUS,RP0
MOVF EEDATA,W
BANKSEL AUX
MOVWF AUX
END

Escribo esto a manera de "jugar" para ver si lo carga correctamente a la direccion 20h del registro, y por supuesto el problema es q no lo esta cargando. Apenas tengo 2 o 3 dias de haberme iniciado en esto asi q encontrar errores me cuesta por ahora
 
Hola!
Aquí les tengo otro programita, por si acaso, nada más.

Código:
;Configuración del PIC 16F84A
STATUS    EQU    0x03
PORTA    EQU    0x05
PORTB    EQU    0x06
TRISA    EQU    0x85
TRISB    EQU    0x86
EECON1    EQU    0x88
EECON2    EQU    0x89        ;Registro virtual
EEDATA    EQU    0x08
EEADR    EQU    0x09
INTCON    EQU    0x0B
W        EQU    0
RD        EQU    0
F        EQU    1
WR        EQU    1
RP0        EQU    5
GIE        EQU    7
WREN    EQU    2

RESULT    EQU    0x0C

;Seteo para la inicialización de puertos del 16F84A
    bsf        STATUS,RP0
    clrf    TRISA
    clrf    TRISB
    bcf        STATUS,RP0
;Limpiar puertos
    clrf    PORTA
    clrf    PORTB

;Ejemplo de escritura
    movlw    0x01            ;Referecia a la posición 01 de la memoria
    movwf    EEADR
    movlw    0x0A            ;Dato a escribir en la posición 01 de la memoria
    movwf    EEDATA
    call    WRITE_EEPROM    ;Mandar a escribir en EEPROM

;Ejemplo de lectura
    movlw    0x01            ;Referecia a la posición 01 de la memoria
    movwf    EEADR
    call    READ_EEPROM        ;Mandar a leer tal dirección
    movwf    RESULT            ;Meter dato leído en RESULT

    goto    FIN                ;Irse al fin.

WRITE_EEPROM        ;Ingrese EEADR y EEDATA (Dirección y dato a escribir)
    bsf        STATUS,RP0            ; Banco 1
    bcf        INTCON,GIE            ; Desactivar interrupciones.
    bsf        EECON1,WREN            ; Activar escritura en EEPROM
    movlw    0x55                ;                         Obligado
    movwf    EECON2                ; Escribir 55h             Obligado
    movlw    0xAA                ;                         Obligado
    movwf    EECON2                ; Escribir AAh             Obligado
    bsf        EECON1,WR            ; Mandar a escribir

    bcf        EECON1,WREN            ; Enable Write
    bcf        STATUS,RP0            ; Banco 0
;      bsf        INTCON,GIE            ; Activar INTs. (Solo para reactivar INTs
    clrw                        ;  por si acaso las tenía activadas de antes)

READ_EEPROM            ;Lea W
    bsf        STATUS,RP0            ; Banco 1
    bsf        EECON1,RD            ; Activar lectura
    bcf        STATUS,RP0            ; Banco 0
    movf    EEDATA,W            ; W = EEDATA
            ;EEDATA guardado en W, después leer de W.

FIN
    goto    FIN

END

;Este programa está hecho de la manera más simple posible para
;que se entienda cómo esribir y leer la EEPROM del PIC.
;Vienen dos subrutinas grandes que se pueden usar fácilmente con
;"call" para grabar o leer.

Saludos!
 
HOLA A TODOS, gracias MARCELO por la información esta muy buena, pero yo tengo una pregunta:
-Diseñé una consola de citofonia con MP 16F877A, en la memoria EEPROM grabamos los numeros correspondientes a cada pin. Por Ejemplo:
RB1=101-RB2=102-RB3=103-RB4=104; Pero resulta que en algunas ocasiones se me borran los números o se alteran y no de toda la memoria EEPROM si no de uno o dos.

Al MP le entran señales de 5V por los pines, pero es posible que este Voltaje se incremente debido a sobre tensiones en la red, puede ser esta la causa de este problema???. Les agradezco cualquier aporte que me puedan hacer.
 
lo mas seguro es que sea un error en tu programa que le ordene al pic sobreescribir los valores de la EEPROM....
 
alguien sabe como se lee y escribe y se borra una eeprom con picbasic?

josb86 dijo:
alguien sabe como se lee y escribe y se borra una eeprom con picbasic?

Upss perdón ya lo encontré simplemente con el comando WRITE perdonen
 
Última edición:
hola tengo problemas para guardar un dato en la eepron del pic 18f2550 en CCS
pongo #rom 2100 {'1','2','3','4'} no recuerdo si es parentecis o corchetes
pero cuando simulo en el proteus en la eepron no guarda nada q se puede hacer
 
Hola!
Yo tengo que pasar un numeros de 14BITs a BCD, entonces necesito saber como utilizar una EEprom, porque me han comentado que la direccion puede ser el numero en binario (00000001111111) y eso tendria como salida el numero en BCD, osea (0000 0000 0001 0010 0111). En otras palabras necesito una Eeprom de 14 inputs y 17 outputs.

¿Hay alguna?
 
Hola A todos .
tengo un problema en gravar la EEPROM del PIC 16f877A.
He seguido las instrucciones del data sheet pero no me funciona.
Si reviso el programa con el debugger, me funciona perfecto , pero en la practica no guarda el ultimo numero.

ESTE ES MI PROGRAMA. por si alguien me puede ayudar. también quiero gravar varias posiciones de memoria.
Con el pic 16F628.
lo pude hacer y grave hasta 16 diferentes valores en la memoria , sin que se borraran al faltar la alimentación, Pero este PIC 16F877A me esta sacando canas verdes.
Gracias
Código:
;    *************************************    7_tes_22.ASM    ********************
;    ************************************    7_tes_20.asm    ****************************
;    ***************************************    7_tes-19.ASN    ****************]
;

    LIST    P=16f877A
    INCLUDE    <P16F877A.INC>

        __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_OFF & _XT_OSC & _LVP_OFF & _BODEN_OFF
    CBLOCK    0x20
    ADDR_L
    DATA_L
    Refresca
    Guarda_DATOS

    Contador
    ENDC



    ORG    0x00
    NOP
    NOP
    GOTO    Inicio
;*************************************
Inicio
    BSF    STATUS,RP0
    BCF    STATUS,RP1
    CLRF    TRISA
    MOVLW    B'00000001'
    MOVWF    TRISB
    MOVLW    B'00000000'
    MOVWF    TRISC
    CLRF    TRISD
    CLRF    TRISE
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVLW    .90
    MOVWF    Refresca
    CLRF    PORTC
    GOTO    Principal
;***********************************
Principal
    MOVF    ADDR_L,W    
    CALL    LEER_EEPROM
    MOVF    Guarda_DATOS,W
    MOVWF    DATA_L
    MOVF    DATA_L,W
    CALL    Visualiza
    BTFSS    PORTB,0
    GOTO    Principal
    CALL    Espere
    GOTO    Incrementa
    GOTO    Principal
;********************************
Espere
    BTFSC    PORTB,0
    GOTO    Espere
    RETURN
;***********************************
Incrementa
    MOVF    Contador,W
    MOVWF    Contador
    INCF    Contador,F
    MOVF    Contador,W
    MOVWF    DATA_L
    MOVF    DATA_L,W
    MOVF    ADDR_L,W
    CALL    ESCRIBIR_EEPROM
    MOVF    DATA_L,W
    MOVWF    Contador
    MOVF    Contador,W
    MOVWF    Guarda_DATOS
    GOTO    Principal
;***********************************
Visualiza
    MOVF    DATA_L,W
    CALL    Tabla
    MOVWF    PORTC
    BSF    PORTC,6
    BCF    PORTC,5
    CALL    Retardo_500micros
    BCF    PORTC,6
    CALL    Retardo_500micros    
    DECFSZ    Refresca,F
    GOTO    Visualiza
    MOVLW    .90
    MOVWF    Refresca
    RETURN
;***********************************
ESCRIBIR_EEPROM
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVF    ADDR_L,W
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVWF    EEADR
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVF    DATA_L,W
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVWF    EEDATA
    BSF    STATUS,RP0
    BSF    STATUS,RP1
    BCF    EECON1,EEPGD
    BSF    EECON1,WREN
    BCF    INTCON,GIE
    MOVLW    55H
    MOVWF    EECON2
    MOVLW    0xAA
    MOVWF    EECON2
    BSF    EECON1,WR
    BSF    INTCON,GIE
Loop
    BTFSC    EECON1,WR
    GOTO    Loop
    BCF    PIR2,EEIF
    BCF    EECON1,WREN
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    RETURN
;******************************
LEER_EEPROM
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVF    ADDR_L,W
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVWF    EEADR
    BSF    STATUS,RP0
    BSF    STATUS,RP1
    BCF    EECON1,EEPGD
    BSF    EECON1,RD
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVF    EEDATA,W
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVWF    DATA_L
    RETURN
;**********************************
Tabla
    ANDLW    B'00001111'
    ADDWF    PCL,F
    RETLW    B'00000000'
    RETLW    B'00000001'
    RETLW    B'00000010'
    RETLW    B'00000011'
    RETLW    B'00000100'
    RETLW    B'00000101'
    RETLW    B'00000110'
    RETLW    B'00000111'
    RETLW    B'00001000'
    RETLW    B'00001001'

    INCLUDE    <RETARDOS.ASM>
    END
 
Última edición por un moderador:
Un ejemplo.

Código:
;************************************ EEPROM_01.asm **********************************
;
;    ====================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS".
;      E. Palacios, F. Remiro y L. López.        www.pic16f84a.com
;       Editorial Ra-Ma.  www.ra-ma.es
;    ====================================================================
;
; Este programa comprueba el funcionamiento de la lectura y escritura en la memoria
; EEPROM de datos. Cada vez que el sistema es reseteado se incrementa un contador que 
; se guarda en la primera posición de la memoria EEPROM de datos del PIC y es visualizado
; en el módulo LCD.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F84A
    INCLUDE        <P16F84A.INC>
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

    CBLOCK   0x0C
    Contador
    ENDC        

    ORG    0x2100                ; Corresponde a la dirección 0 de la zona EEPROM de datos.
    DE    0x00                ; El contador en principio a cero.
    
; ZONA DE CÓDIGOS ********************************************************************

    ORG     0                        ; El programa comienza en la dirección 0.
Inicio
    call    LCD_Inicializa
    clrw                            ; Leerá la primera posición de memoria EEPROM.
    call    EEPROM_LeeDato
    movwf    Contador                ; Se guarda en Contador.
    call    BIN_a_BCD                ; Se visualiza en BCD
    call    LCD_Byte                ; con nibble alto apagado si es cero.
    movlw    MensajeReseteado
    call    LCD_Mensaje
    incf    Contador,W                ; Se incrementa y se graba en 
    call    EEPROM_EscribeDato        ; EEPROM de datos.
Principal
    sleep                            ; Pasa a modo de reposo.
    goto    Principal

; "Mensajes" ----------------------------------------------------------------------------
;
Mensajes
    addwf    PCL,F    
MensajeReseteado
    DT " reseteados.   ", 0x00
FinMensajes

    INCLUDE   <EEPROM.INC>            ; Subrutinas básicas de control de la EEPROM de
    INCLUDE   <RETARDOS.INC>        ; datos del PIC.
    INCLUDE   <BIN_BCD.INC>
    INCLUDE   <LCD_4BIT.INC>
    INCLUDE   <LCD_MENS.INC>
    END

;    ====================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS".
;      E. Palacios, F. Remiro y L. López.        www.pic16f84a.com
;       Editorial Ra-Ma.  www.ra-ma.es
;    ====================================================================


Librería EEPROM.INC
Código:
;***************************** Librería "EEPROM.INC" **********************************
;
;    ====================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS".
;      E. Palacios, F. Remiro y L. López.        www.pic16f84a.com
;       Editorial Ra-Ma.  www.ra-ma.es
;    ====================================================================
;
; Estas subrutinas permiten realizar las tareas básicas de escritura y lectura de la
; memoria EEPROM de datos del PIC.
;
; Subrutina "EEPROM_LeeDato" ------------------------------------------------------------
;
; El microcontrolador lee el dato que hay escrito en la posición de la EEPROM del PIC apuntada
; por el contenido del registro de trabajo W. El resultado se proporciona en el mismo W.
;
; Entrada: En (W) la dirección de la memoria EEPROM a leer.
; Salida :  En (W) el byte leído.

EEPROM_LeeDato
    bcf        STATUS,RP0            ; Asegura que trabaja con el Banco 0.
    movwf    EEADR                ; Dirección a leer.
    bsf        STATUS,RP0            ; Banco 1.
    bsf        EECON1,RD            ; Orden de lectura.
EEPROM_SigueLeyendo
    btfsc    EECON1,RD            ; El PIC indica que ha terminado la lectura
    goto    EEPROM_SigueLeyendo    ; poniendo en bajo este bit.
    bcf        STATUS,RP0            ; Banco 0.
    movf    EEDATA,W            ; El byte leído al registro W.
    return

; Subrutina "EEPROM_EscribeDato" --------------------------------------------------------
;
; Escribe el dato introducido en el registro de trabajo W en la posición de memoria EEPROM del
; PIC apuntada por el registro EEADR.
;
; Como altera el valor del registro INTCON al posicionar el flag GIE, éste se debe guardar al
; principio de la subrutina y restaurarlo al final.
;
; Entradas:    En el registro EEADR la dirección de la memoria EEPROM a escribir.
;        En el registro W el byte a escribir.
;
    CBLOCK
    EEPROM_GuardaINTCON
    ENDC

EEPROM_EscribeDato
    bcf        STATUS,RP0            ; Asegura que trabaja con el Banco 0.
    movwf    EEDATA                ; El byte a escribir.
    movf    INTCON,W            ; Reserva el valor anterior de INTCON
    movwf    EEPROM_GuardaINTCON
    bsf        STATUS,RP0            ; Acceso al Banco 1.
    bcf        INTCON,GIE            ; Deshabilita todas las interrupciones.
    bsf        EECON1,WREN            ; Habilita escritura.
;
; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROM:
;
    movlw    0x55
    movwf    EECON2
    movlw    0xAA
    movwf    EECON2
    bsf        EECON1,WR            ; Inicia la escritura.
EEPROM_TerminaEscribir
    btfsc    EECON1,WR            ; Comprueba que termina de escribir en la EEPROM.
    goto    EEPROM_TerminaEscribir
    bcf        EECON1,WREN            ; Desautoriza la escritura en EEPROM.
    bcf        EECON1,EEIF            ; Limpia este flag.
    bcf        STATUS,RP0            ; Acceso al Banco 0.
    movf    EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
    movwf    INTCON
    return

;    ====================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS".
;      E. Palacios, F. Remiro y L. López.        www.pic16f84a.com
;       Editorial Ra-Ma.  www.ra-ma.es
;    ====================================================================
 
Bueno mis apreciados amigos.
Ayer escribi solicitando ayuda para poder escribir y leer en la memoria EEPROM del PIC 17F877A.
La verdad estaba mas enredado que un bulto de anzuelos.
Agradezco la intervención de Meta.
la grabación y lectura de la EEPROM de datos ya la había realizado con el PIC 16F628. Pero infortunadamente el único que tenia se me dano, y tuve que migrar al 877a. La verdad no lo conozco bien.
Después de muchas canas logre hacer un programita donde gravo 4 posiciones EEPROM, y me las conserva aun después de perder la alimentación.
Es un programa bien TONTO, pero solo es para aprender a como grabarlas,
Imagino debe haber mejores maneras, pero esta fue la única que se ocurrió, y "" Funciono"".
Dejo el programa por si a alguien le puede ayudar . Saludos.


Código:
;*************************************    7_tes_24.ASN;        
;Cesar Alvarez  CAAV_1    

    LIST    P=16f877A
    INCLUDE    <P16F877A.INC>

        __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_OFF & _XT_OSC & _LVP_OFF & _BODEN_OFF

    CBLOCK    0x20        ; Macro para el Cblock desde la posicion 0x20 Comensarea guardar variables            

    DIR_GRAL        ; Variable para las diferentes posiciones
                ; de Memoria que voy a gravar y Leer ( ADRESS)
    DATO            ; Variable para almacenar el dato, QUE: voy a leer y luego 
                ; a Gravar.
    Refresca        ; Demora para la visualizacion
    
    ENDC
    ORG    0x2100        ; Esta es una parte que no he entendido bien
    DE    H'0'        ; Pero la utilize con el pic 16f628
    DE    H'0'        ; y funciona, Ahora bien Si no coloco esto
    DE    H'0'        ; NO FUNCIONARA.
    DE    H'0'        ; Si alguien me puede explicar esta parte lo agradecereia mucho.
                ; Creo que si voy a gravar mas posiciones debere colocar mas DE H'0'


    ORG    0x00
    NOP
    NOP
    GOTO    Inicio
;*************************************
Inicio
    BSF    STATUS,RP0
    BCF    STATUS,RP1
    CLRF    TRISA
    MOVLW    B'00000001'        ; PORTB,0 Como entrada de pulsador
    MOVWF    TRISB
    MOVLW    B'00000000'
    MOVWF    TRISC            ; PORTC  Como Salida para display 7 seg Con DM 7447 
    CLRF    TRISD
    CLRF    TRISE
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVLW    .200
    MOVWF    Refresca        ; Demora para visualizar
    CLRF    PORTC
    MOVLW    0x06
    MOVWF    ADCON1
    MOVLW    .0            ; Comienzo dato en 0
    MOVWF    DATO
    CLRF    EEDATA
    GOTO    Principal
;***********************************
Principal
                    ; primero que todo leo lo que hay en cada posicion
    
                    ; de memoria y luego la visualizo
    MOVLW    .1            ; desde la posicion 1 hasta la 4
    MOVWF    DIR_GRAL
    CALL    LEE_EEPROM
    MOVF    DATO,W
    CALL    Visualiza

    MOVLW    .2            ;  numero de direccion a leer
    MOVWF    DIR_GRAL        ; La cargo a DIR_GRAL para que luego vaya a ADDR
    CALL    LEE_EEPROM
    MOVF    DATO,W            ; Traigo el Dato leido en esta posicion de memoria
    CALL    Visualiza        ; y lo visualizo

    MOVLW    .3
    MOVWF    DIR_GRAL
    CALL    LEE_EEPROM
    MOVF    DATO,W
    CALL    Visualiza

    MOVLW    .4            ; Al comenzar y hasta que no digite el pulsador
    MOVWF    DIR_GRAL        ; se quedara leyendo las 4 posiciones de memoria 
    CALL    LEE_EEPROM
    MOVF    DATO,W            ; y las visualizara
    CALL    Visualiza
;*******************************

    BTFSS    PORTB,0            ; Cuando digito el pulsador
    GOTO    Principal
Uno    BTFSC    PORTB,0            ; Comenzara a gravar en EEPROM
    GOTO    Uno

    MOVLW    .3            ; Coloco el dato que quiero gravar en EEPROM            
    MOVWF    DATO            ; a variable DATO luego ira a EEDATA
    MOVLW    .1            ; Coloco numero de direccion que quiero leer
    MOVWF    DIR_GRAL        ; En  DIR_GRAL luego ira  a EEADR
    CALL    ESCRIBA_EEPROM        ; GRAVO EL NUMERO 3 En LA POSICION 1 DE EEPROM
    ;MOVF    DATO,W

    MOVLW    .6
    MOVWF    DATO
    MOVLW    .2
    MOVWF    DIR_GRAL
    CALL    ESCRIBA_EEPROM        ; ASI susesivamente gravare las 4 posiciones
    ;MOVF    DATO,W
                    ; Este es un ejercicio algo tono 
    MOVLW    .9
    MOVWF    DATO            ; pero lo utilize solo para ver como podia gravar
    MOVLW    .3
    MOVWF    DIR_GRAL
    CALL    ESCRIBA_EEPROM
    ;MOVF    DATO,W

    MOVLW    .1
    MOVWF    DATO
    MOVLW    .4
    MOVWF    DIR_GRAL
    CALL    ESCRIBA_EEPROM
    ;MOVF    DATO,W    

    GOTO    Principal
;********************************

Visualiza
    MOVF    DATO,W            ; Traigo el dato leido de EEPROM de la 
    CALL    Tabla            ; respectiva direccion , llamo la tabla
    MOVWF    PORTC            ; y lo envio al DM 7447 y de ahi al Disp 7 seg
    BSF    PORTC,6            ; Habilito el anodo de Display para que ilumine
    
    CALL    Retardo_500micros    ; Durante este tiempo
    BCF    PORTC,6
    CALL    Retardo_500micros    ; Apago el display durante este tiempo    
    DECFSZ    Refresca,F
    GOTO    Visualiza        ; Visualizare este mnismo dato 200 veces 
    MOVLW    .200            ; con diferncia de 1000micros cada vez 
    MOVWF    Refresca        ; es solo para verlo funcionar mas adelante lo haremos mejor
    RETURN
;***********************************
ESCRIBA_EEPROM
    BCF    STATUS,RP0        ;Estas rutinas son las data sheet PIC 16F87 Para 
    BCF    STATUS,RP1
    MOVF    DIR_GRAL,W        ; Escritura y Lectura
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVWF    EEADR
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVF    DATO,W
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVWF    EEDATA
    BSF    STATUS,RP0
    BSF    STATUS,RP1
    BCF    EECON1,EEPGD
    BSF    EECON1,WREN
    BCF    INTCON,GIE
    MOVLW    55H
    MOVWF    EECON2
    MOVLW    0xAA
    MOVWF    EECON2
    BSF    EECON1,WR
    BSF    INTCON,GIE
Loop
    BTFSC    EECON1,WR
    GOTO    Loop
    BCF    PIR2,EEIF
    BCF    EECON1,WREN
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    RETURN
;******************************
LEE_EEPROM
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVF    DIR_GRAL,W
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVWF    EEADR
    BSF    STATUS,RP0
    BSF    STATUS,RP1
    BCF    EECON1,EEPGD
    BSF    EECON1,RD
    BCF    STATUS,RP0
    BSF    STATUS,RP1
    MOVF    EEDATA,W
    BCF    STATUS,RP0
    BCF    STATUS,RP1
    MOVWF    DATO
    RETURN
;**********************************
Tabla
    ANDLW    B'00001111'
    ADDWF    PCL,F
    RETLW    B'00000000'
    RETLW    B'00000001'
    RETLW    B'00000010'
    RETLW    B'00000011'
    RETLW    B'00000100'
    RETLW    B'00000101'
    RETLW    B'00000110'
    RETLW    B'00000111'
    RETLW    B'00001000'
    RETLW    B'00001001'

    INCLUDE    <RETARDOS.ASM>
    END
 
Última edición por un moderador:
Oigan, tengo una duda. Mi grabador de pics me dice que hay error en la memoria flash del pic16f628a en la posición 0x0000000 . Significa que ya no sirve para nada?
 
Estimados tengo una duda existencial, alguien pudo escribir la EEPROM de un 16f84A. Dado que esto me esta volviendo loco, si bien recién arranco con los microcontroladores ha programado en c durante mucho tiempo por lo que me fue mas fácil comenzar usando CCS. He leído muchos post de este y otros foros tratando de encontrar la forma de hacer esto, el tema esta que las funciones read_eeprom y write_eeprom me funcionan cuando simulo en prteus pero al grabar el pic no puedo escribir, si leer, ya que si modifico la EEPROM en el firmware luego puedo leer los daos, pero no modificarlos. Ha armado distintas variantes incluyendo código ASM dentro del código c y hasta arme un programita en assembler para que me grabe una posición de memoria pero no he logrado que funcione, siempre lo mismo en la simulación anda pero en la vida real no.


Desde ya les agradezco cualquier ayuda que puedan brindarme.

Les dejo los ejemplos con los que estuve probando:

En C:
Código:
#include <16f84a.h>
  //#include <def_F84.h>
  #fuses XT,NOWDT
  #use delay(clock= 4000000)
  #include <lcdpic16f84a.c>
  #use standard_io (A)
  #use standard_io (B)
  int v1,v2,v3;
   
   
  void Leer () {
  v1=read_eeprom (4);
  v2=read_eeprom (5);
  v3=read_eeprom (6);
  }
   
  void Escrbir () {
  write_eeprom (4,4);
  write_eeprom (5,5);
  write_eeprom (6,6);
  }
  void Poncero() {
  write_eeprom (4,0);
  write_eeprom (5,0);
  write_eeprom (6,0);
  }
   
  void main () {
  lcd_init();
  while (1){
        if (input(PIN_A0)==1) { //escribo
        delay_ms (200);
        Escrbir();
        lcd_putc('\f');
        lcd_gotoxy(1,1);
        printf (lcd_putc,"Mem.Escrita");
        }
        if (input(PIN_B0)==1) {//Leo
        delay_ms (200);
        Leer();
        lcd_putc('\f');
        lcd_gotoxy(1,1);
        printf (lcd_putc,"MEM:%u | %u | %u",v1,v2,v3);
        }
        if (input(PIN_A4)==1) {//Borro
        delay_ms (200);
        Poncero();
        lcd_putc('\f');
        lcd_gotoxy(1,1);
        printf (lcd_putc,"Mem.Borrada");     
        }
  }
   
  }
El ASM:

Código:
  ; **** Encabezado ****
  list p=16F84A
  #include P16F84A.inc
  __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
   
  GUARDAR
  BANKSEL    EEDATA
  movf H'A', W  
  movwf EEDATA
  movlw H'18'
  movwf EEADR
  bcf INTCON, GIE
  bsf STATUS,RP0
  bcf EECON1,WRERR
  bsf EECON1,WREN
  movlw H'55'
  movwf EECON2
  movlw H'AA'
  movwf EECON2
  bsf EECON1,WR
  ES1 nop
  btfss EECON1,EEIF
  goto ES1
  nop
  btfsc EECON1,WRERR
  goto GUARDAR
  nop
  bcf EECON1,EEIF
  bcf EECON1,WREN
  bcf STATUS,RP0
  bsf INTCON, GIE
  ESPERA
  nop
  goto ESPERA
  end
 
Última edición por un moderador:
Me respondo a mi mismo.
Despues de un dia sin dormir (algunos diran, esta loco, pero bue, soy asi) les cuento que el problema aparentemente estaba en el osilador dado que probe con otro pic, un 16f873 que es mucho mas groso que 16f84 para descartar problemas de el chip y ademas como estoy usando CCS quiza el codigo que generase fuera distinto, me paso exactamente lo mismo hasta que reubique el xtal, lo puse lo mas cerca que pude del pic y magicamente empezo a funcionar,es verdad lo que se dice que el xtal tiene que estar lo mas proximo el pic posible, este caso lo demuestra. Una vez que funciono el 16f873 hize lo mismo para el 16f84 y "magia otra vez" ya los tengo andando.

Si les intereza les puedo subir el proyecto completitio asi lo usan como base para ortas cosas o se arman un temporizador que llega has 225 hs 59 mins 59 sec.


Saludos a todos.

PD: las funciones que use para grabar y escribir son las que vienen con CCs write_eeprom y read_eeprom.
 
compañeros soy nuevo en esto de microprosesadores me podrian enseñar o dar una idea de como hacer un programa que tenga un cliclo que cuando sea 10 se termine

saludos :D
 
Estado
Cerrado para nuevas respuestas.
Atrás
Arriba