Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

30/04/2013 #1

Avatar de Meta

Comportamiento del PIC que no entiendo
Hola:

Usando el PIC16F88 he programado un pulsador. Que al encender el PIC tiene un estado, un Led a la salida. El PIC funciona bien al pulsar el pulsador. Ahora, quiero guardar los datos del Led en la EEPROM interna. Hago estos pasos.

1) Al encender PIC.
2) El Led por defecto aparece encendido cuando la realidad tiene que estar apagado.
3) Apago el Led con el pulsador.
4) Apago el PIC16F88.
5) Enciendo el PIC16F88.
6) El Led aparece apagado.
7) Vuelvo apagar el PIC.
8) Enciendo el PIC y el Led está encendido siempre.
¿Por qué ocurre esto?
Así que la EEPROM no funciona bien. Cambio de PIC16F88 por otro y ocurre lo mismo.
30/04/2013 #2

Avatar de Daniel Meza

Quizá un error en la rutina de almacenamiento de datos en la EEPROM. ¿Puedes colocarla por acá?
30/04/2013 #3

Avatar de Meta

Aquí está el código. Lo he probado en la Protoboard que es cuando vez si realmente funciona bien o no.

Código:
LIST P=16F88
        INCLUDE <P16F88.INC>
        __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_OFF & _WDT_OFF & _FOSC_EC
        __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
        ERRORLEVEL -302
        CBLOCK 0x20
        RAM_ret
        RAM_ret_1
        ENDC
        CBLOCK 0x110
        Dato
        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
        clrw
        clrf PORTB ; Borra los latch de salida.
        BANKSEL ANSEL
        clrf ANSEL ; Puerto A digital.
        BANKSEL TRISA
        movlw b'11111111'
        bsf Pulsador ; Pulsador activado como entrada.
        clrf TRISB
;;;;;;;        bcf Led ; Activar como salida Led.
        call    Lee_Dato_EEPROM;;;;;;;call    Lee_Dato_EERPOM_2 
        BANKSEL PORTA ; Vuelve al banco 0.
    
        ;;;;;;; Recupera estado del LED de la EEProm
        andlw  b'00000001'  ;;;;;;;
        btfsc  STATUS,Z     ;;;;;;;
        goto   LED_off      ;;;;;;;
LED_on
        bsf Led ; Estaba encendido.;;;;;;;
        goto   Principal    ;;;;;;;
LED_off       
        bcf Led ; Estaba apagado.;;;;;;;
        BANKSEL TRISB   ;;;;;;;;;;;;;;;
        bcf Led ; Activar como salida Led con estado EEProm.;;;;;;;
        BANKSEL PORTA ; Vuelve al banco 0. ;;;;;;;

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 b'00000001'
        ;;;;;;;BANKSEL Dato
        movf Led
 BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
        goto EsperaDejePulsar
EstabaEncendido
        bcf Led ; Estaba encendido y lo apaga.
        ;movlw b'00000000'
        movf Led
 BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
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. 
        movf Dato,W
        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  Retardos.

; Delay = 0.02 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.02 seconds = 20000 cycles
; Error = 0 %

    cblock
    RAM
    RAM_1
    endc

Retardo_20ms
            ;19993 cycles
    movlw    0x9E
    movwf    RAM
    movlw    0x10
    movwf    RAM_1
Retardo_20ms_0
    decfsz    RAM, f
    goto    $+2
    decfsz    RAM_1, f
    goto    Retardo_20ms_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return
        END
Saludo.
30/04/2013 #4

Avatar de Daniel Meza

Al parecer las rutinas de lectura/escritura están bien... veamos, ¿al leer el PIC con el programador se observa la modificación de los datos?
30/04/2013 #5

Avatar de Meta

Si, se ve que cambia de valor. Lo he depurado y comprobado desde la Demoboard al clone PicKit 2en tiempo real.

El programa principal y mejor ejemplo es el indicado abajo. La cuestión es, donde cargar la lectura de la EEPROM y cuando guargarla.
30/04/2013 #6
Moderador

Avatar de D@rkbytes

Meta dijo: Ver Mensaje

8) Enciendo el PIC y el Led está encendido siempre.
¿Por qué ocurre esto?
Así que la EEPROM no funciona bien. Cambio de PIC16F88 por otro y ocurre lo mismo.
Ocurre porque al iniciar la lectura de la EEPROM, el registro EEDATA contiene 0xFF
Puede ser que durante el POR ó el BOR contenga xxxxxxxx, pero lo mejor es iniciarlo en 0x00.

Así que, en tu subrutina de lectura de la EEPROM, agrega esto...

Código:
;Subrutina EEPROM ******************************************************************
Lee_Dato_EEPROM
        BANKSEL EEADR
        movlw 0x00 ; Dirección.
        clrf    EEDATA     ; Limpiar el buffer antes de leer la memoria.
        movwf EEADR ; Carga el registro EEADR con la dirección que se desea leer.
        BANKSEL EECON1
Prueba así y nos comentas el resultado.

Saludos.
30/04/2013 #7

Avatar de Meta

D@rkbytes dijo: Ver Mensaje
Ocurre porque al iniciar la lectura de la EEPROM, el registro EEDATA contiene 0xFF
Puede ser que durante el POR ó el BOR contenga xxxxxxxx, pero lo mejor es iniciarlo en 0x00.

Así que, en tu subrutina de lectura de la EEPROM, agrega esto...

Código:
;Subrutina EEPROM ******************************************************************
Lee_Dato_EEPROM
        BANKSEL EEADR
        movlw 0x00 ; Dirección.
        clrf    EEDATA     ; Limpiar el buffer antes de leer la memoria.
        movwf EEADR ; Carga el registro EEADR con la dirección que se desea leer.
        BANKSEL EECON1
Prueba así y nos comentas el resultado.

Saludos.
Es curioso, no hace nada esa instrucción en el simulador del MPLAB ni en el depurador del PicKit 2.

clrf EEDATA ; Limpiar el buffer antes de leer la memoria.

Saludo.

Edito:
Si funciona lo del código de arriba.
El funcionamiento me pasa lo mismo, no hay manera de que se guarde bien la EEPROM.

Edito 2
Funciona el clrf EEDATA, cuando le da la gana, esto no es normal.
30/04/2013 #8
Moderador

Avatar de D@rkbytes

Pues si, al parecer no responde el clrf EEDATA.
Y debe ser porque después de la lectura, toma el valor de la posición 0x00, que al iniciar está en 0xFF
Por lo tanto queda de sobra limpiar el buffer, ya que posteriormente adquirirá el valor de la lectura.

Yo he resuelto la lectura inicial de 255, haciendo una comparación.

Suerte.
30/04/2013 #9

Avatar de Daniel Meza

EstabaApagado
bsf Led ; Estaba apagado y lo enciende.
;movlw b'00000001'
;;;;;;;BANKSEL Dato
movf Led
BANKSEL Dato;;;;;;;
movwf Dato
call Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2

me parece rara la instrucción "movf Led", led es solo una variable de un bit, intenta mejor con movf PORTB,W y luego ANDLW 0x01, con esto consideras solo el bit de menor peso del puerto B (el del led) y luego MOVWF Dato y finalmente llamar a la subrutina para almacenar el byte
01/05/2013 #10

Avatar de Meta

Hola:

Pues no, no pasa nada, sigue el mismo comportamiento.
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.
;
; http://www.alos.5u.com/pic16f877/Modulo6.html#Protecci%C3%B3n%20contra%20escrituras%20espurias
; 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
        RAM_ret
        RAM_ret_1
        ENDC
        CBLOCK 0x110
        Dato
        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
        clrw
        clrf PORTB ; Borra los latch de salida.
        BANKSEL ANSEL
        clrf ANSEL ; Puerto A digital.
        BANKSEL TRISA
        movlw b'11111111'
        bsf Pulsador ; Pulsador activado como entrada.
        clrf TRISB
;;;;;;;        bcf Led ; Activar como salida Led.
        call    Lee_Dato_EEPROM;;;;;;;call    Lee_Dato_EERPOM_2 
        BANKSEL PORTA ; Vuelve al banco 0.
    
        ;;;;;;; Recupera estado del LED de la EEProm
        andlw  b'00000001'  ;;;;;;;
        btfsc  STATUS,Z     ;;;;;;;
        goto   LED_off      ;;;;;;;
LED_on
        bsf Led ; Estaba encendido.;;;;;;;
        goto   Principal    ;;;;;;;
LED_off       
        bcf Led ; Estaba apagado.;;;;;;;
        BANKSEL TRISB   ;;;;;;;;;;;;;;;
        bcf Led ; Activar como salida Led con estado EEProm.;;;;;;;
        BANKSEL PORTA ; Vuelve al banco 0. ;;;;;;;

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 b'00000001'
        ;;;;;;;BANKSEL Dato
        ;movf Led
        movf    PORTB,W    ; ################## AQUÍ #######################
        ANDLW    0x01
 BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
        goto EsperaDejePulsar
EstabaEncendido
        bcf Led ; Estaba encendido y lo apaga.
        ;movlw b'00000000'
        movf Led
 BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
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
        clrf    EEDATA     ; Limpiar el buffer antes de leer la memoria.
        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. 
        movf Dato,W
        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  Retardos.

; Delay = 0.02 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.02 seconds = 20000 cycles
; Error = 0 %

    cblock
    RAM
    RAM_1
    endc

Retardo_20ms
            ;19993 cycles
    movlw    0x9E
    movwf    RAM
    movlw    0x10
    movwf    RAM_1
Retardo_20ms_0
    decfsz    RAM, f
    goto    $+2
    decfsz    RAM_1, f
    goto    Retardo_20ms_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return
    END
El código principal sin EEPROM es este, encender y apagar un Led mediante un pulsador, usar la EEPROM para almacenar sus estados de salida es otro cantar:
Código:
#DEFINE Pulsador    PORTA,4        ; Pulsador conectado a RA4.
#DEFINE LED            PORTB,1        ; Línea donde se conecta el diodo LED.

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

    ORG    0                        ; El programa comienza en la dirección 0.
Inicio
     bsf        STATUS,RP0            ; Acceso al Banco 1.
    bsf        Pulsador            ; La línea RA4 se configura como entrada.
    bcf        LED                    ; Se configura como salida.
    bcf        STATUS,RP0            ; Acceso al Banco 0.
    bcf        LED                    ; En principio diodo LED apagado.
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.
Fin
    goto    Principal

    INCLUDE <RETARDOS.INC>
    END
Sólo hay que grabar la EEPROM en su momento adecuado, también leerlo claro.

Se puede hacer un alibrería externa que puede ser este, para leer y grabar la santa EEPROM de las narices que me tiene loco.

Código:
; 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
    BANKSEL    EEADR
    movwf    EEADR                ; Dirección a leer.
    BANKSEL    EECON1
    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.
    BANKSEL    EEDATA
    movf    EEDATA,W            ; El byte leído al registro W.
    BANKSEL    PORTA                ; Banco 0.
    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
    BANKSEL    EEDATA
    movwf    EEDATA                ; El byte a escribir.
    movf    INTCON,W            ; Reserva el valor anterior de INTCON
    movwf    EEPROM_GuardaINTCON
    BANKSEL    INTCON
    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.
    BANKSEL    PORTA                ; Vuelve al Banco principal, Banco 0.
    movf    EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
    movwf    INTCON
    return
Saludo.
01/05/2013 #11

Avatar de Daniel Meza

Creo ver que al momento de leer el dato de la EEPROM lo lees de la dirección 0xFF la cual es inválida para el PIC.

Código:
        movlw b'11111111'
        bsf Pulsador ; Pulsador activado como entrada.
        clrf TRISB
;;;;; bcf Led ; Activar como salida Led.
        call    Lee_Dato_EEPROM;;;;;;;call    Lee_Dato_EERPOM_2
El parámetro que se pasa a la rutina de lectura es la dirección contenida en W
01/05/2013 #12

Avatar de Meta

Parace ser que tu idea tiene razón, lo he modificado y ahora en el PIC en la Demmoboard me funciona la EEPROM.

desde el inicio puse 0x00 a EEDATA.
Código:
Inicio
        clrw
        clrf PORTB ; Borra los latch de salida.
        BANKSEL ANSEL
        clrf ANSEL ; Puerto A digital.
        BANKSEL TRISA
        movlw b'11111111'
        bsf Pulsador ; Pulsador activado como entrada.
        clrf TRISB
;;;;;;;        bcf Led ; Activar como salida Led.
        movlw    0x00
        BANKSEL    EEDATA
        movwf    EEDATA
        call    Lee_Dato_EEPROM;;;;;;;call    Lee_Dato_EERPOM_2 
        BANKSEL PORTA ; Vuelve al banco 0.

Código completo.
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.
;
; http://www.alos.5u.com/pic16f877/Modulo6.html#Protecci%C3%B3n%20contra%20escrituras%20espurias
; 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
        RAM_ret
        RAM_ret_1
        ENDC
        CBLOCK 0x110
        Dato
        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
        clrw
        clrf PORTB ; Borra los latch de salida.
        BANKSEL ANSEL
        clrf ANSEL ; Puerto A digital.
        BANKSEL TRISA
        movlw b'11111111'
        bsf Pulsador ; Pulsador activado como entrada.
        clrf TRISB
;;;;;;;        bcf Led ; Activar como salida Led.
        movlw    0x00
        BANKSEL    EEDATA
        movwf    EEDATA
        call    Lee_Dato_EEPROM;;;;;;;call    Lee_Dato_EERPOM_2 
        BANKSEL PORTA ; Vuelve al banco 0.
    
        ;;;;;;; Recupera estado del LED de la EEProm
        andlw  b'00000001'  ;;;;;;;
        btfsc  STATUS,Z     ;;;;;;;
        goto   LED_off      ;;;;;;;
LED_on
        bsf Led ; Estaba encendido.;;;;;;;
        goto   Principal    ;;;;;;;
LED_off       
        bcf Led ; Estaba apagado.;;;;;;;
        BANKSEL TRISB   ;;;;;;;;;;;;;;;
        bcf Led ; Activar como salida Led con estado EEProm.;;;;;;;
        BANKSEL PORTA ; Vuelve al banco 0. ;;;;;;;

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 b'00000001'
        ;;;;;;;BANKSEL Dato
        ;movf Led
        movf    PORTB,W    ; ################## AQUÍ #######################
        ANDLW    0x01
 BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
        goto EsperaDejePulsar
EstabaEncendido
        bcf Led ; Estaba encendido y lo apaga.
        ;movlw b'00000000'
        movf Led
 BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
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
        clrf    EEDATA     ; Limpiar el buffer antes de leer la memoria.
        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. 
        movf Dato,W
        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  Retardos.

; Delay = 0.02 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.02 seconds = 20000 cycles
; Error = 0 %

    cblock
    RAM
    RAM_1
    endc

Retardo_20ms
            ;19993 cycles
    movlw    0x9E
    movwf    RAM
    movlw    0x10
    movwf    RAM_1
Retardo_20ms_0
    decfsz    RAM, f
    goto    $+2
    decfsz    RAM_1, f
    goto    Retardo_20ms_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return
    END
Ya me graba sin problemas el PIC16F88.

Hay otro problema, sufra antirebores, le pongo el Call Retardos_20ms y el Led siempre se queda encendido. Nunca cambia de estado por mucho que pulse el pulsador.
01/05/2013 #13

Avatar de Daniel Meza

Muy bien... pero almacenabas el valor en el registro de datos no en el de direcciones de la EEPROM (EEADR); ahora para el tema de los rebotes está bien tu rutina pero es necesario también agregar un retardo después de que se libera el botón ya que también la acción de soltar el botón produce rebotes; entonces, después de confirmar la liberación del botón vuelve a llamar a la rutina de retardo y finalmente regresa al bucle principal
25/05/2013 #14

Avatar de Meta

Daniel Meza dijo: Ver Mensaje
Muy bien... pero almacenabas el valor en el registro de datos no en el de direcciones de la EEPROM (EEADR); ahora para el tema de los rebotes está bien tu rutina pero es necesario también agregar un retardo después de que se libera el botón ya que también la acción de soltar el botón produce rebotes; entonces, después de confirmar la liberación del botón vuelve a llamar a la rutina de retardo y finalmente regresa al bucle principal
Pues no, añadí otro call Retardo_20ms y no pasa nada, el PIC ni se inmuta.

Ejemplo:
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
        RAM_ret
        RAM_ret_1
        ENDC
        CBLOCK 0x110
        Dato
        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
        clrw
        clrf PORTB ; Borra los latch de salida.
        BANKSEL ANSEL
        clrf ANSEL ; Puerto A digital.
        BANKSEL TRISA
        movlw b'11111111'
        bsf Pulsador ; Pulsador activado como entrada.
        clrf TRISB
;;;;;;;        bcf Led ; Activar como salida Led.
        movlw    0x00
        BANKSEL    EEDATA
        movwf    EEDATA
        call    Lee_Dato_EEPROM;;;;;;;call    Lee_Dato_EERPOM_2 
        BANKSEL PORTA ; Vuelve al banco 0.
    
        ;;;;;;; Recupera estado del LED de la EEProm
        andlw  b'00000001'  ;;;;;;;
        btfsc  STATUS,Z     ;;;;;;;
        goto   LED_off      ;;;;;;;
LED_on
        bsf Led ; Estaba encendido.;;;;;;;
        goto   Principal    ;;;;;;;
LED_off       
        bcf Led ; Estaba apagado.;;;;;;;
        BANKSEL TRISB   ;;;;;;;;;;;;;;;
        bcf Led ; Activar como salida Led con estado EEProm.;;;;;;;
        BANKSEL PORTA ; Vuelve al banco 0. ;;;;;;;

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.
        call Retardo_20ms ; Espera que se estabilicen los niveles de tensión.
        btfsc Led ; Testea el último estado del LED.
        goto EstabaEncendido
EstabaApagado
        bsf Led ; Estaba apagado y lo enciende.
        ;movlw b'00000001'
        ;;;;;;;BANKSEL Dato
        ;movf Led
        movf    PORTB,W    ; ################## AQUÍ #######################
        ANDLW    0x01
         BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
        goto EsperaDejePulsar
EstabaEncendido
        bcf Led ; Estaba encendido y lo apaga.
        ;movlw b'00000000'
        movf Led
         BANKSEL Dato;;;;;;;
        movwf Dato
        call    Escribe_Dato_EERPOM;;;;;;;call Escribe_Dato_EERPOM_2
        BANKSEL PORTA ; Banco 0.
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
        clrf    EEDATA     ; Limpiar el buffer antes de leer la memoria.
        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. 
        movf Dato,W
        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  Retardos.

; Delay = 0.02 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.02 seconds = 20000 cycles
; Error = 0 %

    cblock
    RAM
    RAM_1
    endc

Retardo_20ms
            ;19993 cycles
    movlw    0x9E
    movwf    RAM
    movlw    0x10
    movwf    RAM_1
Retardo_20ms_0
    decfsz    RAM, f
    goto    $+2
    decfsz    RAM_1, f
    goto    Retardo_20ms_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return
    END
25/05/2013 #15

Avatar de fdesergio

A mi modo de ver, personalmente no uso banksel, pero no deberias regresar al banco 0 despues de usar esa instruccion??? bueno es una directiva pero como no la conozco...ella misma regresa al banco de origen??? contame aunque segun lo que lei NO, chauuuuuuuu

Actualizado:

ah ya lei bien sobre ella, segun lei ubica el banco donde esta el REG llamado, actua sobre el y continua en el banco que estaba, chauuuuuuu

bueno mirando el codigo solo veo que en la escrituras omitiste BLOQUEAR las INTs, no esta de mas usarlo, igual no la vas a usar como indicacion de fin de escritura, chauuuuuuuuu
25/05/2013 #16

Avatar de Meta

Hola:
La directiva banksel


El nombre de esta directiva es un acrónimo de BANK SELection y, como se prevé, sirve para cambiar de bancos.
Como sabemos, la RAM de los PICmicros de familias Baseline y Midrange se divide en varios bancos por los que tenemos que ir saltando para acceder a sus registros, “jugando” con los bits RP0 y RP1, del registro STATUS, así:
Tabla RP1 RP0 RP1 RP0 Banco accedido 0 0 Banco 0 0 1 Banco 1 1 0 Banco 2 1 1 Banco 3
En los PIC con dos bancos, como el PIC16F84A, solo se trabaja con el bit RP0.
Dado el tedio que puede acarrear este trabajo, sobre todo si no recordamos a qué banco pertenece un registro, la directiva banksel puede ser de gran ayuda. Banksel se encargará de colocar las instrucciones necesarias para acceder al registro que se le indica como parámetro.
banksel TRISA ; Seleccionar banco del registro TRISA (Banco 1)

Explicado aquí.

Que yo sepa, no vuelve al banco donde estaba, tienes que ponerlo. Si me estás diciendo que en algún lugar se me ha olvidado volver al banco donde estaba, me dices donde. Gracias por el aviso.

Un saludo.
30/05/2013 #17

Avatar de Meta

Ahora me toca lo mismo con el PIC16F886 probando. No hay manera de hecharlo andar.

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

    LIST        P=16F886
    INCLUDE        <P16F886.INC>
    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _EC_OSC
    __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V 
    ERRORLEVEL -302    

    CBLOCK 0x110
    Dato
    ENDC

Direccion    EQU    0x10

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

; ZONA DE CÓDIGOS ********************************************************************
    ORG    0x2100
    DE 0x00
    
    ORG    0                        ; El programa comienza en la dirección 0.
Inicio
    clrf     PORTB                ;Borra los latch de salida
    BANKSEL    ANSEL
    clrf    ANSEL                ;Puerta A digital
    clrf    ANSELH                ;Puerta B digital
    BANKSEL    TRISB
    clrf    TRISB                ;RB7:RB0 se configuran como salida
    movlw    b'11111111'        
    movwf    TRISA                ;RA5:RA0 se configuran como entrada

    call    Lee_EEPROM
    BANKSEL    PORTA

        ;;;;;;; Recupera estado del Led de la EEProm
        andlw  b'00000001'  ;;;;;;;
        btfsc  STATUS,Z     ;;;;;;;
        goto   Led_off      ;;;;;;;
Led_on
        bsf Led ; Estaba encendido.;;;;;;;
        goto   Principal    ;;;;;;;
Led_off       
        bcf Led ; Estaba apagado.;;;;;;;
        BANKSEL TRISB   ;;;;;;;;;;;;;;;
        bcf Led ; Activar como salida Led con estado EEProm.;;;;;;;
        BANKSEL PORTA ; Vuelve al banco 0. ;;;;;;; 

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.
;    call    Retardo_20ms        ; Espera que se estabilicen los niveles de tensión.
    btfsc    Led                    ; Testea el último estado del Led.
     goto    EstabaEncendido
EstabaApagado
    bsf        Led                    ; Estaba apagado y lo enciende.
    call    Escribe_EEPROM
    goto    EsperaDejePulsar
EstabaEncendido
    bcf        Led                    ; Estaba encendido y lo apaga.
    call    Escribe_EEPROM
EsperaDejePulsar
    btfss    Pulsador            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar    ; No. Espera que deje de pulsar.
Fin
    goto    Principal

;Subrutina EEPROM**********************************************************************+

Lee_EEPROM
    BANKSEL EEADR ;
    MOVLW     Direccion ;
    MOVWF     EEADR ;Data Memory
;Address to read
    BANKSEL EECON1 ;
    BCF     EECON1, EEPGD ;Point to DATA memory
    BSF     EECON1, RD ;EE Read
    BANKSEL EEDAT ;
    MOVF     EEDAT, W ;W = EEDAT
    BCF     STATUS, RP1 ;Bank 0
    return

Escribe_EEPROM
    BANKSEL EEADR ;
    MOVLW     Direccion ;
    MOVWF     EEADR ;Data Memory Address to write
    MOVLW     Dato ;
    MOVWF     EEDAT ;Data Memory Value to write
    BANKSEL EECON1 ;
    BCF     EECON1, EEPGD ;Point to DATA memory
    BSF     EECON1, WREN ;Enable writes
    BCF     INTCON, GIE ;Disable INTs.
    BTFSC     INTCON, GIE ;SEE AN576
    GOTO     $-2
    MOVLW     0x55
    MOVWF     EECON2 ;Write 55h
    MOVLW     0xAA
    MOVWF     EECON2 ;Write AAh
    BSF     EECON1, WR ;Set WR bit to begin write
    BSF     INTCON, GIE ;Enable INTs.
;SLEEP ;Wait for interrupt to signal write complete
    BCF     EECON1, WREN ;Disable writes
    BCF     STATUS, RP0 ;Bank 0
    BCF     STATUS, RP1
    return

    INCLUDE <RETARDOS.INC>
    END
Aún así me centro en el PIC16F88.
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.