Grabar pulsadores en la EEPROM.

Hola:

Quiero grabar un estado de un pulsador en su EEPROM interna.

imagen01-615768.gif


Si es posible, de una forma más elegante, jajja. Este pulsador tiene antirrebote, por si alguien le pica la curiosidad. Cada pulsación se queda grabado en su EEPROM interna, concretamente en el PIC16F88. Se que en la página 29 te lo indica muy general. El PIC tiene que ser capaz de leer los datos almacenados cuando se reinicia o lo vuelves a encender.

El código del pulsador es este:

Código:
; Cada vez que presiona el pulsador conectado a la línea RA0 conmutará el estado de
; un LED conectado a la línea RB0.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F88
    INCLUDE        <P16F88.INC>
    __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _FOSC_EC
    __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

    CBLOCK 0x20
    ENDC

#DEFINE Pulsador1    PORTA,0        ; Pulsador conectado a RA0.
#DEFINE Led1        PORTB,0        ; Línea donde se conecta el diodo LED.


; ZONA DE CÓDIGOS ********************************************************************

    ORG     0
Inicio
    clrf    PORTB               ; Borra los latch de salida.
    BANKSEL ANSEL
    clrf    ANSEL               ; Puerto A digital.
    BANKSEL TRISB
    bsf     Pulsador1           ; Pulsador activado como entrada.
    BANKSEL TRISA
    bcf     Led1                ; Activar como salida Led1.
    BANKSEL PORTA               ; Vuelve al banco 0.
Principal
    btfsc    Pulsador1            ; ¿Pulsador presionado?, ¿(Pulsador)=0?
    goto    Fin                    ; No. Vuelve a leerlo.
    call    Retardo_20ms        ; Espera que se estabilicen los niveles de tensión.
    btfsc    Pulsador1            ; Comprueba si es un rebote.
    goto    Fin                    ; Era un rebote y sale fuera.
    btfsc    Led1                ; Testea el último estado del LED.
     goto    EstabaEncendido
EstabaApagado
    bsf        Led1                ; Estaba apagado y lo enciende.
    goto    EsperaDejePulsar
EstabaEncendido
    bcf        Led1                ; Estaba encendido y lo apaga.
EsperaDejePulsar
    btfss    Pulsador1            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar    ; No. Espera que deje de pulsar.
Fin
    goto    Principal

    INCLUDE <RETARDOS.INC>
    END

Saludo.
 
me imagino que debe ser en caso de un corte de energia electrica inesperado y cuando vuelva la energia lea el estado en la eeprom... como algunos equipos de aire acondicionados
 
Hola:

Por ahora hice esto, en el proteus parece ser que no funciona o no se hacerlo.

¿Cómo puedo saber en el Proteus 7.10 SP0 que los datos se guardan?

Voy a pprobalro físicamente y le muestro vídeos o fotos.

Código:
; Cada vez que presiona el pulsador conectado a la línea RA0 conmutará el estado de
; un LED conectado a la línea RB0.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F88
    INCLUDE        <P16F88.INC>
    __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _FOSC_EC
    __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

    CBLOCK 0x20
    ENDC

#DEFINE Pulsador1    PORTA,0        ; Pulsador conectado a RA0.
#DEFINE Led1        PORTB,0        ; Línea donde se conecta el diodo LED.


; ZONA DE CÓDIGOS ********************************************************************
    ORG     0x2100
    DE      0xFF

    ORG     0
Inicio
    clrf    PORTB               ; Borra los latch de salida.
    BANKSEL ANSEL
    clrf    ANSEL               ; Puerto A digital.
    BANKSEL TRISB
    bsf     Pulsador1           ; Pulsador activado como entrada.
    BANKSEL TRISA
    bcf     Led1                ; Activar como salida Led1.
    BANKSEL PORTA               ; Vuelve al banco 0.


;Leyendo el byte de la 0x00 EEPROM se puede determinar si es la primera vez que se usa, o ésta
;ya tiene un nº de turno válido
    clrf    EEADR            ;Selecciona dirección 00 de EEPROM.
    call    EEPROM_Lee            ;Lee byte de la EEPROM.
    BANKSEL EEDATA           ;Selecciona banco 2.
    movlw    0xFF
    subwf    EEDATA,W
    bcf     STATUS,RP0
    bcf        STATUS,RP1        ;Banco 0
    btfss    STATUS,Z        ;Es la 1ª vez que se usa la EEPROM ??
    goto    Datos            ;No, el sistema ya se ha usado
    bcf     Led1
Datos
    BANKSEL EEDATA
    movf    EEDATA,W            ;Lee el valor actual.
    bcf     STATUS,RP0
    bcf        STATUS,RP1        ;Banco 0

    BANKSEL EEDATA
    movwf    EEDATA            ;Valor del contador a grabar en la EEPROM
    clrf    EEADR            ;Dirección 0x00 de la EEPROM
    call    EEPROM_Escribe        ;Graba el nuevo valor del contador en la EEPROM


Principal
    btfsc    Pulsador1            ; ¿Pulsador presionado?, ¿(Pulsador)=0?
    goto    Fin                    ; No. Vuelve a leerlo.
    call    Retardo_20ms        ; Espera que se estabilicen los niveles de tensión.
    btfsc    Pulsador1            ; Comprueba si es un rebote.
    goto    Fin                    ; Era un rebote y sale fuera.
    btfsc    Led1                ; Testea el último estado del LED.
     goto    EstabaEncendido
EstabaApagado
    bsf        Led1                ; Estaba apagado y lo enciende.
    goto    EsperaDejePulsar
EstabaEncendido
    bcf        Led1                ; Estaba encendido y lo apaga.
EsperaDejePulsar
    btfss    Pulsador1            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar    ; No. Espera que deje de pulsar.
Fin
    goto    Principal

;****************************************************************************************
;EEPROM_Escribe: Graba un byte en la EEPROM de datos. La dirección será la contenida en EEADR y
;el dato se le supone previamente metido en EEDATA.

EEPROM_Escribe
    BANKSEL EECON1
    bcf        EECON1,EEPGD    ;Acceso a EEPROM de datos
    bsf        EECON1,WREN        ;Permiso de escritura
    movlw      b'01010101'
    movwf      EECON2
    movlw      b'10101010'
    movwf      EECON2            ;Secuencia establecida por Microchip
    bsf        EECON1,WR        ;Orden de escritura
Espera
    btfsc      EECON1,WR        ;Testear flag de fin de escritura
    goto       Espera
    bcf        EECON1,WREN        ;Desconecta permiso de escritura
    bcf        EECON1,EEIF        ;Reponer flag de fin de escritura
    bcf        STATUS,RP0
    bcf        STATUS,RP1        ;Selecciona banco 0
    return

;**************************************************************************************
;EEPROM_Lee: Leer un byte de la EEPROM. Se supone al registro EEADR cargado con la direc-
;ción a leer. En EEDAT aparecerá el dato leído.

EEPROM_Lee
    BANKSEL EECON1
    bcf        EECON1,EEPGD    ;Selecciona EEPROM de datos
    bsf        EECON1,RD        ;Orden de lectura
    bcf        STATUS,RP0
    bcf        STATUS,RP0        ;Selección de banco 0
    return

    INCLUDE <RETARDOS.INC>
    END
Saludo.

WEdito:
No me guarda o lee nada en la EEPROM. Lo pruebo dejando el pulsador con el Led activado. Luego apago el PIc y lo vuelvo a encender, no guarda los valores o no lo lee.

2504201337653-616006.jpg


Vídeo.
https://www.youtube.com/watch?v=L4kXZX4fgMI

¿Alguna idea?
 
Última edición:
Hola:

Por ahora he hecho esto.
Código:
; Cada vez que presiona el pulsador conectado a la línea RA0 conmutará el estado de
; un LED conectado a la línea RB0.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F88
    INCLUDE     <P16F88.INC>
    __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _FOSC_EC
    __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF
    ERRORLEVEL -302

    CBLOCK 0x20
    Dato
    RAM_ret
    RAM_ret_1
    ENDC

#DEFINE Pulsador    PORTA,0         ; Pulsador conectado a RA0.
#DEFINE Led         PORTB,0         ; Línea donde se conecta el diodo LED.


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

    ORG     0
Inicio
    clrf    PORTB                   ; Borra los latch de salida.
    BANKSEL ANSEL
    clrf    ANSEL                   ; Puerto A digital.
    BANKSEL TRISB
    bsf     Pulsador                ; Pulsador activado como entrada.
    BANKSEL TRISA
    bcf     Led                     ; Activar como salida Led.
    BANKSEL EEDATA
    movf    EEDATA,W
    BANKSEL PORTA                   ; Vuelve al banco 0.
    movwf   Dato                    ; Dato.
Principal
    btfsc   Pulsador                ; ¿Pulsador presionado?, ¿(Pulsador)=0?
    goto    Fin                     ; No. Vuelve a leerlo.
    call    Retardo_20ms            ; Espera que se estabilicen los niveles de tensión.
    btfsc   Pulsador                ; Comprueba si es un rebote.
    goto    Fin                     ; Era un rebote y sale fuera.
    btfsc   Led                     ; Testea el último estado del LED.
    goto    EstabaEncendido
EstabaApagado
    bsf     Led                     ; Estaba apagado y lo enciende.
    goto    EsperaDejePulsar
EstabaEncendido
    bcf     Led                     ; Estaba encendido y lo apaga.
EsperaDejePulsar
    btfss   Pulsador                ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar        ; No. Espera que deje de pulsar.
    movwf    EEDATA                    ;Valor de la salida a grabar en la EEPROM.
    clrf    EEADR                    ;Dirección 0x00 de la EEPROM.
    call    Escribe_Dato_EERPOM        ;Graba el nuevo valor del contador en la EEPROM.
Fin
    goto    Principal

;Subrutina EEPROM ******************************************************************
Lee_Dato_EEPROM
    BANKSEL EEADR
    movlw   0x00                    ; Dirección.
    movwf   EEADR                   ; Carga el registro EEADR con la dirección que se desea leer.
    BANKSEL EECON1
    bcf     EECON1,EEPGD            ; Selecciona el acceso a memoria EEPROM.
    bsf        EECON1,RD               ; Inicia el ciclo de lectura.
    BANKSEL EEDATA
    movf    EEDATA,W                ; Carga en W ek dato recuén leído.
    return

;Guarda en la EEPROM el valor de la salida.
Escribe_Dato_EERPOM
    BANKSEL EEADR
    movlw   0x00                    ; Dirección.
    movwf   EEADR                   ; Carga registro EEADR con la dirección a escribir.
    movlw   Dato
    movwf   EEDATA                  ; Carga el registro EEDATA con el dato a escribir.
    BANKSEL EECON1
    bcf     EECON1,EEPGD            ; Selecciona acceso a memoria EEPROM de datos.
    bsf     EECON1,WREN             ; Permiso de escritura.
    movlw   0x55
    movwf   EECON2
    movlw   0xAA
    movwf   EECON2                  ; Secuencia de escritura según Mirochip.
    bsf     EECON1,WR               ; Inicio del ciclo de escritura.
Espera
    btfsc   EECON1,WR
    goto    Espera                  ; Esperar que finalice (WR=0).
    bcf     EECON1,WREN             ; Retira el permiso de escritura.
    return

;Subrutina Retardo_20ms ************************************************************
 ; Retardo = 0.02 segundos.
; Frecuencia Reloj = 4 MHz.
; Retardo actual = 0.02 segundos = 20000 ciclos.

Retardo_20ms
            ;19993 ciclos.
    movlw    0x9E
    movwf    RAM_ret
    movlw    0x10
    movwf    RAM_ret_1
Retardo_20ms_0
    decfsz    RAM_ret, f
    goto    $+2
    decfsz    RAM_ret_1, f
    goto    Retardo_20ms_0
            ;3 ciclos.
    goto    $+1
    nop
            ;4 ciclos (incluyendo call).
    return

    END

Algo no me cuaja. ¿Alguna idea?
 
Si te preguntas porque no funciona es por la siguiente linea
& _FOSC_EC que esta donde se configura los fuses
Borra y corre el programa
Sobre si graba o no en la eeprom no lo se, aun no he revisado este tema en los pics

salu2
 
Hola:

_FOSC_EC lo debo usar porque lo uso físicamente. Ya lo pasaré a XT en el futuro próximo a su versión final.

He usado call Lee_Dato_EEPROM y call Escribe_Dato_EEPROM pero no se si es adecuadamente.

Lo que me pasa ahora es lo siguiente:

1) El dato de la EEPROM es FF en la posición de la memoria 0x00. Al leer la primera vez lo lee como 0xFF. (Tengo en cuenta que uso solo un pulsador y una salida para un Led, en el futuro lo ampliaré a 4 pulsadores y 4 Leds).

2) Otra cosa que me pasa y no se el motivo exacto, nunca sale de la zona del código en rojo, está como bloqueado. Puedo encender el Led, pero al pulsar de nuevo el pulsador, no se apaga más, se queda como atascado.

;Guarda en la EEPROM el valor de la salida.
Escribe_Dato_EERPOM
BANKSEL EEADR
movlw 0x00 ; Dirección.
movwf EEADR ; Carga registro EEADR con la dirección a escribir.
movlw Dato
movwf EEDATA ; Carga el registro EEDATA con el dato a escribir.
BANKSEL EECON1
bcf EECON1,EEPGD ; Selecciona acceso a memoria EEPROM de datos.
bsf EECON1,WREN ; Permiso de escritura.
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2 ; Secuencia de escritura según Mirochip.
bsf EECON1,WR ; Inicio del ciclo de escritura.
Espera
btfsc EECON1,WR
goto Espera ; Esperar que finalice (WR=0).

bcf EECON1,WREN ; Retira el permiso de escritura.
return

El código completo del programa es:
Código:
; Cada vez que presiona el pulsador conectado a la línea RA0 conmutará el estado de
; un LED conectado a la línea RB0.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F88
    INCLUDE     <P16F88.INC>
    __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _FOSC_EC
    __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF
    ERRORLEVEL    -302
    
    CBLOCK 0x20
    Dato
    RAM_ret
    RAM_ret_1
    ENDC

#DEFINE Pulsador    PORTA,0        ; Pulsador conectado a RA0.
#DEFINE Led        PORTB,0        ; Línea donde se conecta el diodo LED.


; ZONA DE CÓDIGOS ********************************************************************

    ORG     0
Inicio
    clrf    PORTB               ; Borra los latch de salida.
    BANKSEL ANSEL
    clrf    ANSEL               ; Puerto A digital.
    bsf     Pulsador           ; Pulsador activado como entrada.
    BANKSEL TRISA
    bcf     Led                ; Activar como salida Led.
    call    Lee_Dato_EEPROM
    BANKSEL PORTB               ; Vuelve al banco 0.
    movwf    PORTB
Principal
    btfsc   Pulsador            ; ¿Pulsador presionado?, ¿(Pulsador)=0?
    goto    Fin                    ; No. Vuelve a leerlo.
    call    Retardo_20ms        ; Espera que se estabilicen los niveles de tensión.
    btfsc   Pulsador            ; Comprueba si es un rebote.
    goto    Fin                    ; Era un rebote y sale fuera.
    btfsc   Led                ; Testea el último estado del LED.
    goto    EstabaEncendido
EstabaApagado
    bsf     Led                ; Estaba apagado y lo enciende.
    movlw    PORTB
    movwf    Dato
    call    Escribe_Dato_EERPOM
    goto    EsperaDejePulsar
EstabaEncendido
    bcf     Led                ; Estaba encendido y lo apaga.
    movlw    PORTB
    movwf    Dato
    call    Escribe_Dato_EERPOM
EsperaDejePulsar
    btfss   Pulsador            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar    ; No. Espera que deje de pulsar.
Fin
    goto    Principal

;Subrutina EEPROM ******************************************************************
Lee_Dato_EEPROM
    BANKSEL EEADR
    movlw   0x00                    ; Dirección.
    movwf   EEADR                   ; Carga el registro EEADR con la dirección que se desea leer.
    BANKSEL EECON1
    bcf     EECON1,EEPGD            ; Selecciona el acceso a memoria EEPROM.
    bsf        EECON1,RD               ; Inicia el ciclo de lectura.
    BANKSEL EEDATA
    movf    EEDATA,W                ; Carga en W el dato recuén leído.
    return

;Guarda en la EEPROM el valor de la salida.
Escribe_Dato_EERPOM
    BANKSEL EEADR
    movlw   0x00                    ; Dirección.
    movwf   EEADR                   ; Carga registro EEADR con la dirección a escribir.
    movlw   Dato
    movwf   EEDATA                  ; Carga el registro EEDATA con el dato a escribir.
    BANKSEL EECON1
    bcf     EECON1,EEPGD            ; Selecciona acceso a memoria EEPROM de datos.
    bsf     EECON1,WREN             ; Permiso de escritura.
    movlw   0x55
    movwf   EECON2
    movlw   0xAA
    movwf   EECON2                  ; Secuencia de escritura según Mirochip.
    bsf     EECON1,WR               ; Inicio del ciclo de escritura.
Espera
    btfsc   EECON1,WR
    goto    Espera                  ; Esperar que finalice (WR=0).
    bcf     EECON1,WREN             ; Retira el permiso de escritura.
    return

;Subrutina Retardo_20ms ************************************************************
 ; Retardo = 0.02 segundos.
; Frecuencia Reloj = 4 MHz.
; Retardo actual = 0.02 segundos = 20000 ciclos.

Retardo_20ms
            ;19993 ciclos.
    movlw    0x9E
    movwf    RAM_ret
    movlw    0x10
    movwf    RAM_ret_1
Retardo_20ms_0
    decfsz    RAM_ret, f
    goto    $+2
    decfsz    RAM_ret_1, f
    goto    Retardo_20ms_0
            ;3 ciclos.
    goto    $+1
    nop
            ;4 ciclos (incluyendo call).
    return

    END

Por ahora esto es lo que me pasa.

Saludo.
 
Atrás
Arriba