Modificar este código a algo más complejo

#21
Entendido. Es mejor ver los bits para tener las cosas claras.



El siguiente y último reto que nunca he usado la EEPROM interna del PIC16F88, no me sale a pesar de leer bien su hoja de datos. En la página 29 del datasheet te dice códigos pero a mi no me funciona o no se hacerlo.

Lo que quiero hacer es guardar los últimos datos seleccionados por el pulsador de las dos tablas de la verdad. Por ejemplo, si estamos en el número 2 del Display, al apagarlo y encenderlo otra vez el PIC, aparezca precisamente el 2, que es el último número que se mostró. Se incluye también el guardado de la tabla de la verdad de datos.

Ver el archivo adjunto 115023

Los que sepan, una ayudita. Por lo que veo, no se me da para nada bien guardar y recuperar datos en la EEPROM interna del PIC. Fijándome bien, se necesita una celda para guardar los 8 bits o un byte de la Tabla de la verdad gris del Display, y otra celda o posición de memoria también de 8 bits o un byte en la Tabla de la verdad verde de datos.

Ver el archivo adjunto 115070

De todas formas, voy a intentarlo por si acaso.

Desde que funcione todo, subo un vídeo.

Saludo.
 
Última edición:
#22
No necesitas dos posiciones de la EEPROM para guardar la información. Solo necesitas una (la del contador).

El código para leer y escribir en la EEPROM está en la hoja que muestras. Tienes que agregarlo en tu código. El de lectura, antes del bucle principal, cuando se inicializa a 0 el contador, lo cambias por la lectura de la EEPROM (aquí pondría un and para asegurarme de que sólo guardo un valor de 1 a 4). Y luego, en el bucle principal, al final, poner la escritura de la EEPROM (guardar el contador).



Una pregunta de curiosidad...

En las imágenes estoy viendo que estás usando el USB-PIC School, así que asumo que el PIC que estas usando es el de color negro de 18 patillas que está en la parte superior.

Pero... ¿qué chip es el de color naranja que está pinchado en la placa de prototipos?

Y, ¿por qué usas un display de 7 segmentos en la placa? El USB-PIC School tiene dos ya integrados.

Por otra parte... ¿qué tal es ese USB-PIC School? Parece que tiene buena pinta. ¿Lo puedes programar desde el MPLAB X?
 
Última edición:
#23
No necesitas dos posiciones de la EEPROM para guardar la información. Solo necesitas una (la del contador).

El código para leer y escribir en la EEPROM está en la hoja que muestras. Tienes que agregarlo en tu código. El de lectura, antes del bucle principal, cuando se inicializa a 0 el contador, lo cambias por la lectura de la EEPROM (aquí pondría un and para asegurarme de que sólo guardo un valor de 1 a 4). Y luego, en el bucle principal, al final, poner la escritura de la EEPROM (guardar el contador).

Lo intentaré, ahora me toca copiar el código.



Una pregunta de curiosidad...

En las imágenes estoy viendo que estás usando el USB-PIC School, así que asumo que el PIC que estas usando es el de color negro de 18 patillas que está en la parte superior.

Compré la versión DELUXE completa junto con el libro, tiene muchos ejemplos en asm y en C.
Aquí hice tres impresiones por si quiere saber más detalle cuando lo compré.


Pero... ¿qué chip es el de color naranja que está pinchado en la placa de prototipos?

Es un encapsulado de 8 resistencias de 330 Ω cada una en paralelo.

Y, ¿por qué usas un display de 7 segmentos en la placa? El USB-PIC School tiene dos ya integrados.

Porque el que te viene en la placa son de ánodo común y el que vamos a usar para un proyecto es de cátodo común, así de simple.

Es más, voy hacer una placa por mi mismo con más módulos que aquí no caben, como EEPROM por I2C 24LC256, Display de 7 segmentos de cátoco común, LCD de 20x4 y otro tipo LCD gráfico, y mucho más sensores. Como el USB'PICSchool tiene módulo de expanción para otra placa que voy hacer, aprovecho, es una buena ventaja.
Lo mejor de todo, que sus módulos le va muy bien con Arduino.

Por otra parte... ¿qué tal es ese USB-PIC School? Parece que tiene buena pinta. ¿Lo puedes programar desde el MPLAB X?

No lo he probado aún con el MPLAB X. Funciona muy bien con el MPLAB 8.92 y como depurador. El grabador de USB'PICSCHOOL es actualizable, en realidad es un clone de PicKit 2. Como tiene conector ICSP, te vale un grabador externo PicKit 3 si lo desea, ya que esta placa está preparado para ello.

Como no uso el depurador desde hace tiempo. Intentaré hacer pruebas si MPLAB X lo reconoce. Con el MPLAB 8, graba directamente a la placa. Normalmente suelo usar "PICKit 2 Programmer" para grabar PIC, es más rápido.

Lo bueno del USB, que puedes usar la placa desde el PC programándolo con FlowCode.
¿Alguna otra pregunta, caballero?

La verdad que estoy muy contento con esta placa.

Un cordial saludo.
 
#24
No se guarda los datos en la EEPORM, algo no hago bien.

Código:
;
; Un pulsador en RA4 va incrementando un contador, entre [1-4].
; La salida se envía a un display de 7 seg. en PORTB, y hacia salidas en PORTA.
;
; (Contador)  |RB 76543210 |RA 76543210
; ------------|------------------------
;       1     |   00000011 |   00000010
;       2     |   00100100 |   00000101
;       3     |   00001100 |   00000110
;       4     |   00111100 |   00001001
;
; PORTA:
;  RA0 : OE1
;  RA1 : OE2
;  RA2 : A21
;  RA3 : AUX
;  RA4 : Pulsador
; PORTB : display de 7 segmentos. a = RB0
;

; ZONA DE DATOS ****************************************************************

;*******************************************************************************
; Listado y condiciones de ensamblado

    LIST   P=16F88          ; 4 Mhz
    radix       dec
    errorlevel  -302            ; Turn off banking message

;*******************************************************************************
; Bibliotecas

    INCLUDE <P16f88.INC>

;*******************************************************************************
; Fusibles

    __CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
;_XT_OSC

; _CP_OFF: Protección de código DESACTIVADO.
; _DEBUG_OFF: Debug en circuito DESACTIVADO.
; _WRT_PROTECT_OFF: Protección a escritura en memoria de programa DESACTIVADO.
; _CPD_OFF: Protección de código de datos DESACTIVADO.
; _LVP_OFF: Programación en baja tensión DESACTIVADO.
; _BODEN_OFF: Reset por Brown-out DESACTIVADO.
; _MCLRE_ON: Reset por pin externo ACTIVADO.
; _PWRTE_ON: Retraso al reset ACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _XT_OSC: Oscilador externo del tipo XT.

    __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

; _IESO_OFF: Modo de intercambio de externo a interno DESACTIVADO.
; _FCMEN_OFF: Monitor de CLK DESACTIVADO.


;*******************************************************************************
; Definiciones

; Máscaras de E/S de los puertos
; 0 = salida, 1 = entrada
;                    |76543210|
#define PORTA_ES    b'00010000'
#define PORTB_ES    b'00000000'

;*******************************************************************************
; Variables
area_compartida:    udata_shr

contador            res 1                       ; Contador [1-4]


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

programa:           code

                    ORG     000h

Inicio:
                    banksel ANSEL           ; bank 1
                    clrf    ANSEL           ; Puerto analógico a digital.
                    movlw   PORTA_ES        ; definir E/S puerto A
                    movwf   TRISA
                    movlw   PORTB_ES        ; definir E/S puerto B
                    movwf   TRISB
;
                    movlw   0               ; inicializamos contador
                    movwf   contador
                    call    Leer_EEPROM     ; Lectura de la EEPROM.

; Bucle principal
                    BANKSEL OSCCON
                    movlw   b'01100000'     ; 4 MHz
                    movwf   OSCCON
                    banksel PORTA           ; bank 0, siempre
                    goto Inicializado
Principal:
                    movf    PORTA, w        ; leer puerto A
                    andlw   PORTA_ES        ; nos quedamos sólo con lo interesante

                    btfss   STATUS, Z       ; ¿Se ha pulsado? Lo está si RA4 == 0
                    goto    Principal       ; No, esperar
;
; Aquí llegamos con el botón pulsado
Inicializado:
                    call    incrementa_contador
                    call    visualiza_contador
                    call    salida_hacia_A

; Esperamos que levante el botón
Espera_levantar:
                    call    Retardo_100ms   ; Esperar la suelta del pulsador
                    movf    PORTA, w        ; leer puerto A
                    andlw   PORTA_ES        ; nos quedamos sólo con lo interesante
                    btfsc   STATUS, Z       ; ¿Sigue pulsado? Lo está si RA4 == 0
                    goto    Espera_levantar ; No, esperar
;
                    goto    Principal


; ******************************************************************************
;; salida_hacia_A
;
; Según el valor del contador ([1-4]), lo transforma en otro, basado en una
; tabla y lo saca por el puerto A
;

salida_hacia_A:     call    transforma_contador
                    movwf   PORTA           ; visualiza en puerto A
                    return

transforma_contador:
                    decf    contador,w      ; leemos el contador y le restamos 1
                    addwf   PCL, f          ; saltamos dentro de la tabla

;                            |76543210|
                    retlw   b'00000010'
                    retlw   b'00000101'
                    retlw   b'00000110'
                    retlw   b'00001001'

; ******************************************************************************
;; incrementa_contador
;
; Incrementa el valor de la variable contador, entre 1 y 4, inclusives.
;

incrementa_contador:
                    bcf     contador,2
                    incf    contador
                    return

; ******************************************************************************
;; visualiza_contador
;
; Muestra el valor del contador en el display de 7 segmentos
;

visualiza_contador:
                    movfw   contador        ; leemos contador
                    call    w_a_digito      ; transformación a dígito 7 segmentos
                    movwf   PORTB           ; visualiza en puerto B
                    return

w_a_digito:         addwf   PCL, f          ; salta al dígito indexado por w

;                            |76543210|
                    retlw   b'00111111'     ; 0
                    retlw   b'00000110'     ; 1
                    retlw   b'01011011'     ; 2
                    retlw   b'01001111'     ; 3
                    retlw   b'01100110'     ; 4
                    retlw   b'01101101'     ; 5
                    retlw   b'01111101'     ; 6
                    retlw   b'00000111'     ; 7
                    retlw   b'01111111'     ; 8
                    retlw   b'01101111'     ; 9

; ----------------------------------------------------------------------------------------------------
; Espera = 100ms
; Frecuencia de reloj = 4Mhz
;
; Espera real = 0.1 segundos = 100000 ciclos
; Error = 0.00 %

Retardo_par:        udata_shr

Retardo_100ms_d1    res 1
Retardo_100ms_d2    res 1


Retardo_code:       code

Retardo_100ms:
                                    ;99993 ciclos
                    movlw   0x1E
                    movwf   Retardo_100ms_d1
                    movlw   0x4F
                    movwf   Retardo_100ms_d2

Retardo_100ms_loop:
                    decfsz  Retardo_100ms_d1, f
                    goto    $+2
                    decfsz  Retardo_100ms_d2, f
                    goto    Retardo_100ms_loop

                                    ;3 ciclos
                    goto    $+1
                    nop

                                    ;4 ciclos (incluyendo la llamada)
                    return

                    call    Escribir_EEPROM

; Generado por delay_pic.pl (Joaquín Ferrero. 2014.07.22)
; ./delay_pic.pl -s Retardo_100ms 4Mhz 100ms
; mar 22 jul 2014 19:22:23 CEST
; http://perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
; ----------------------------------------------------------------------------------------------------

; ******************************************************************************

;Subrutinas EEPROM -----------------------------------------------------------

Leer_EEPROM
    BANKSEL EEADR           ; Selecciona el registro EEADR.
    movf    contador, W
    movwf   EEADR           ; Dato dirección de momoria a leer.
    BANKSEL EECON1          ; Selecciona el banco EECON1.
    bcf     EECON1, EEPGD    ; Punto a memoria de datos
    bsf     EECON1, RD      ; a Leer.
    BANKSEL EEDATA          ; Seleccionar banco de EEDATA.
    movf    EEDATA, W       ; W = EEDATA.
    return

Escribir_EEPROM
    BANKSEL EECON1          ; Selecciona banco de EECON1.
    btfsc   EECON1, WR      ; Espera para escribir
    goto    $-1             ; a completar.
    BANKSEL EEADR           ; Selecciona el banco EEADR.
    movf    contador, W
    movwf   EEADR           ; Dirección dato de memoria a escribir.
    BANKSEL EECON1          ; Selecciona el banco EECOn1.
    bcf     EECON1, EEPGD   ; Punto a dato de memoria.
    bsf     EECON1, WREN    ; Activar escritura.
    bcf     INTCON, GIE     ; Desactiva interrupciones.

; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROm.

    movlw   0x55
    movwf   EECON2          ; Escribe 55h.
    movlw   0xAA
    movwf   EECON2          ; Escribe AAh.
    bsf     EECON1, WR

    bsf     INTCON, GIE     ; Activa interrupciones.
    bcf     EECON1, WREN    ; Desactiva escrituras.


                END
Saludo.
 
Última edición:
#25
Es cierto que llamas a Leer_EEPROM, pero... ¿te das cuenta de que cuando regresas de la subrutina has cambiado de banco? Debes volver al bank 0.

Y el Escribir_EEPROM... aunque lo has puesto en el código, no lo estás llamando desde ningún sitio. La llamada call está fuera del código que ejecuta el programa.

Prueba a poner el call dentro de la subrutina incrementa_contador, entre la instrucción incf y el return.

Además... le falta un return. Además... tiene el mismo problema que al leer: cambia de banco.
 
#26
Hola:

No graba. Hice este. Algo se me escapa.

Código:
;
; Un pulsador en RA4 va incrementando un contador, entre [1-4].
; La salida se envía a un display de 7 seg. en PORTB, y hacia salidas en PORTA.
;
; (Contador)  |RB 76543210 |RA 76543210
; ------------|------------------------
;       1     |   00000011 |   00000010
;       2     |   00100100 |   00000101
;       3     |   00001100 |   00000110
;       4     |   00111100 |   00001001
;
; PORTA:
;  RA0 : OE1
;  RA1 : OE2
;  RA2 : A21
;  RA3 : AUX
;  RA4 : Pulsador
; PORTB : display de 7 segmentos. a = RB0
;

; ZONA DE DATOS ****************************************************************

;*******************************************************************************
; Listado y condiciones de ensamblado

    LIST   P=16F88          ; 4 Mhz
    radix       dec
    errorlevel  -302            ; Turn off banking message

;*******************************************************************************
; Bibliotecas

    INCLUDE <P16f88.INC>

;*******************************************************************************
; Fusibles

    __CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
;_XT_OSC

; _CP_OFF: Protección de código DESACTIVADO.
; _DEBUG_OFF: Debug en circuito DESACTIVADO.
; _WRT_PROTECT_OFF: Protección a escritura en memoria de programa DESACTIVADO.
; _CPD_OFF: Protección de código de datos DESACTIVADO.
; _LVP_OFF: Programación en baja tensión DESACTIVADO.
; _BODEN_OFF: Reset por Brown-out DESACTIVADO.
; _MCLRE_ON: Reset por pin externo ACTIVADO.
; _PWRTE_ON: Retraso al reset ACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _XT_OSC: Oscilador externo del tipo XT.

    __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

; _IESO_OFF: Modo de intercambio de externo a interno DESACTIVADO.
; _FCMEN_OFF: Monitor de CLK DESACTIVADO.


;*******************************************************************************
; Definiciones

; Máscaras de E/S de los puertos
; 0 = salida, 1 = entrada
;                    |76543210|
#define PORTA_ES    b'00010000'
#define PORTB_ES    b'00000000'

;*******************************************************************************
; Variables
area_compartida:    udata_shr

contador            res 1                       ; Contador [1-4]


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

programa:           code

                    ORG     000h

Inicio:
                    banksel ANSEL           ; bank 1
                    clrf    ANSEL           ; Puerto analógico a digital.
                    movlw   PORTA_ES        ; definir E/S puerto A
                    movwf   TRISA
                    movlw   PORTB_ES        ; definir E/S puerto B
                    movwf   TRISB
;
                    movlw   0               ; inicializamos contador
                    movwf   contador
                    call    Leer_EEPROM     ; Lectura de la EEPROM.

; Bucle principal
                    BANKSEL OSCCON
                    movlw   b'01100000'     ; 4 MHz
                    movwf   OSCCON
                    banksel PORTA           ; bank 0, siempre
                    goto Inicializado
Principal:
                    movf    PORTA, w        ; leer puerto A
                    andlw   PORTA_ES        ; nos quedamos sólo con lo interesante

                    btfss   STATUS, Z       ; ¿Se ha pulsado? Lo está si RA4 == 0
                    goto    Principal       ; No, esperar
;
; Aquí llegamos con el botón pulsado
Inicializado:
                    call    incrementa_contador
                    call    visualiza_contador
                    call    salida_hacia_A

; Esperamos que levante el botón
Espera_levantar:
                    call    Retardo_100ms   ; Esperar la suelta del pulsador
                    movf    PORTA, w        ; leer puerto A
                    andlw   PORTA_ES        ; nos quedamos sólo con lo interesante
                    btfsc   STATUS, Z       ; ¿Sigue pulsado? Lo está si RA4 == 0
                    goto    Espera_levantar ; No, esperar
;
                    goto    Principal


; ******************************************************************************
;; salida_hacia_A
;
; Según el valor del contador ([1-4]), lo transforma en otro, basado en una
; tabla y lo saca por el puerto A
;

salida_hacia_A:     call    transforma_contador
                    movwf   PORTA           ; visualiza en puerto A
                    return

transforma_contador:
                    decf    contador,w      ; leemos el contador y le restamos 1
                    addwf   PCL, f          ; saltamos dentro de la tabla

;                            |76543210|
                    retlw   b'00000010'
                    retlw   b'00000101'
                    retlw   b'00000110'
                    retlw   b'00001001'

; ******************************************************************************
;; incrementa_contador
;
; Incrementa el valor de la variable contador, entre 1 y 4, inclusives.
;

incrementa_contador:
                    bcf     contador,2
                    incf    contador
                    call    Escribir_EEPROM ; Escribir dato en la EEPROM.
                    return

; ******************************************************************************
;; visualiza_contador
;
; Muestra el valor del contador en el display de 7 segmentos
;

visualiza_contador:
                    movfw   contador        ; leemos contador
                    call    w_a_digito      ; transformación a dígito 7 segmentos
                    movwf   PORTB           ; visualiza en puerto B
                    return

w_a_digito:         addwf   PCL, f          ; salta al dígito indexado por w

;                            |76543210|
                    retlw   b'00111111'     ; 0
                    retlw   b'00000110'     ; 1
                    retlw   b'01011011'     ; 2
                    retlw   b'01001111'     ; 3
                    retlw   b'01100110'     ; 4
                    retlw   b'01101101'     ; 5
                    retlw   b'01111101'     ; 6
                    retlw   b'00000111'     ; 7
                    retlw   b'01111111'     ; 8
                    retlw   b'01101111'     ; 9

; ----------------------------------------------------------------------------------------------------
; Espera = 100ms
; Frecuencia de reloj = 4Mhz
;
; Espera real = 0.1 segundos = 100000 ciclos
; Error = 0.00 %

Retardo_par:        udata_shr

Retardo_100ms_d1    res 1
Retardo_100ms_d2    res 1


Retardo_code:       code

Retardo_100ms:
                                    ;99993 ciclos
                    movlw   0x1E
                    movwf   Retardo_100ms_d1
                    movlw   0x4F
                    movwf   Retardo_100ms_d2

Retardo_100ms_loop:
                    decfsz  Retardo_100ms_d1, f
                    goto    $+2
                    decfsz  Retardo_100ms_d2, f
                    goto    Retardo_100ms_loop

                                    ;3 ciclos
                    goto    $+1
                    nop

                                    ;4 ciclos (incluyendo la llamada)
                    return

; Generado por delay_pic.pl (Joaquín Ferrero. 2014.07.22)
; ./delay_pic.pl -s Retardo_100ms 4Mhz 100ms
; mar 22 jul 2014 19:22:23 CEST
; http://perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
; ----------------------------------------------------------------------------------------------------

; ******************************************************************************

;Subrutinas EEPROM -----------------------------------------------------------

Leer_EEPROM
    BANKSEL EEADR           ; Selecciona el registro EEADR.
    movf    contador, W
    movwf   EEADR           ; Dato dirección de momoria a leer.
    BANKSEL EECON1          ; Selecciona el banco EECON1.
    bcf     EECON1, EEPGD    ; Punto a memoria de datos
    bsf     EECON1, RD      ; a Leer.
    BANKSEL EEDATA          ; Seleccionar banco de EEDATA.
    movf    EEDATA, W       ; W = EEDATA.
    BANKSEL PORTA
    return

Escribir_EEPROM
    BANKSEL EECON1          ; Selecciona banco de EECON1.
    btfsc   EECON1, WR      ; Espera para escribir
    goto    $-1             ; a completar.
    BANKSEL EEADR           ; Selecciona el banco EEADR.
    movf    contador, W
    movwf   EEADR           ; Dirección dato de memoria a escribir.
    BANKSEL EECON1          ; Selecciona el banco EECOn1.
    bcf     EECON1, EEPGD   ; Punto a dato de memoria.
    bsf     EECON1, WREN    ; Activar escritura.
    bcf     INTCON, GIE     ; Desactiva interrupciones.

; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROm.

    movlw   0x55
    movwf   EECON2          ; Escribe 55h.
    movlw   0xAA
    movwf   EECON2          ; Escribe AAh.
    bsf     EECON1, WR

    bsf     INTCON, GIE     ; Activa interrupciones.
    bcf     EECON1, WREN    ; Desactiva escrituras.
    BANKSEL PORTA
    return

                END
 
#27
En Leer_EEPROM, no estás indicando de forma correcta la dirección de la EEPROM que hay que leer... y lo mismo para Escribir_EEPROM.

Vamos a ver: una cosa es "contador" (una dirección de la SRAM donde se guarda el valor del contador), y otra cosa distinta es la dirección de la EEPROM donde quieres guardar y leer el valor del contador.

(Si lo pensamos bien, resulta que este problema ya no necesita que contador esté en la SRAM, y podría bastar con que estuviera en la EEPROM, pero si tenemos una copia en la SRAM es más rápido para leer).

Entonces... lo que tienes que decidir es qué dirección de la EEPROM quieres usar para guardar el dato del contador.

Lo dice la documentación en el primer párrafo: «Para leer un dato de una posición de memoria, el usuario debe escribir la dirección en el registro EEADR, limpiar el bit de control EEPGD (EECON1<7>) y entonces activar el bit de control RD (EECON1<0>)».

La cuestión ahora es saber qué direcciones de la EEPROM tienes disponibles. Eso depende del PIC que estés usando.

¿Tienes 128 o 256 bytes de EEPROM? Bueno, al final, da igual. Solo necesitas una dirección. Podría ser la 0 :)

Bueno, pues ya tienes adjudicada esa dirección. Debes modificar las dos subrutinas para que accedan/escriban a/en ella.

Y... en Leer_EEPROM, acuérdate de guardar el valor leído de la EEPROM, en la variable contador (tampoco lo tienes puesto).
 
Última edición:
#28
Hola:

He puesto este códig por ahora incompleto.

Código:
; ###############################################################################
                    BANKSEL EEADR
                    clrf    EEADR            ; Selecciona dirección 00 de EEPROM.
                    call    Leer_EEPROM     ; Lectura de la EEPROM.


                    BANKSEL EEDATA
                    movlw    0xFF
                    subwf    EEDATA,W
                    BANKSEL PORTA           ;Banco 0
                    btfss    STATUS,Z        ;Es la 1ª vez que se usa la EEPROM ??
                    goto    Inicializado            ;No, el sistema ya se ha usado.
                    clrf    contador

; ###############################################################################
Código principal para que veas como está.
Código:
;
; Un pulsador en RA4 va incrementando un contador, entre [1-4].
; La salida se envía a un display de 7 seg. en PORTB, y hacia salidas en PORTA.
;
; (Contador)  |RB 76543210 |RA 76543210
; ------------|------------------------
;       1     |   00000011 |   00000010
;       2     |   00100100 |   00000101
;       3     |   00001100 |   00000110
;       4     |   00111100 |   00001001
;
; PORTA:
;  RA0 : OE1
;  RA1 : OE2
;  RA2 : A21
;  RA3 : AUX
;  RA4 : Pulsador
; PORTB : display de 7 segmentos. a = RB0
;

; ZONA DE DATOS ****************************************************************

;*******************************************************************************
; Listado y condiciones de ensamblado

    LIST   P=16F88          ; 4 Mhz
    radix       dec
    errorlevel  -302            ; Turn off banking message

;*******************************************************************************
; Bibliotecas

    INCLUDE <P16f88.INC>

;*******************************************************************************
; Fusibles

    __CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
;_XT_OSC

; _CP_OFF: Protección de código DESACTIVADO.
; _DEBUG_OFF: Debug en circuito DESACTIVADO.
; _WRT_PROTECT_OFF: Protección a escritura en memoria de programa DESACTIVADO.
; _CPD_OFF: Protección de código de datos DESACTIVADO.
; _LVP_OFF: Programación en baja tensión DESACTIVADO.
; _BODEN_OFF: Reset por Brown-out DESACTIVADO.
; _MCLRE_ON: Reset por pin externo ACTIVADO.
; _PWRTE_ON: Retraso al reset ACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _XT_OSC: Oscilador externo del tipo XT.

    __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

; _IESO_OFF: Modo de intercambio de externo a interno DESACTIVADO.
; _FCMEN_OFF: Monitor de CLK DESACTIVADO.


;*******************************************************************************
; Definiciones

; Máscaras de E/S de los puertos
; 0 = salida, 1 = entrada
;                    |76543210|
#define PORTA_ES    b'00010000'
#define PORTB_ES    b'00000000'

;*******************************************************************************
; Variables
area_compartida:    udata_shr

contador            res 1                       ; Contador [1-4]


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

programa:           code

                    ORG     000h

Inicio:
                    banksel ANSEL           ; bank 1
                    clrf    ANSEL           ; Puerto analógico a digital.
                    movlw   PORTA_ES        ; definir E/S puerto A
                    movwf   TRISA
                    movlw   PORTB_ES        ; definir E/S puerto B
                    movwf   TRISB
;
                    movlw   0               ; inicializamos contador
                    movwf   contador

; ###############################################################################
                    BANKSEL EEADR
                    clrf    EEADR            ; Selecciona dirección 00 de EEPROM.
                    call    Leer_EEPROM     ; Lectura de la EEPROM.


                    BANKSEL EEDATA
                    movlw    0xFF
                    subwf    EEDATA,W
                    BANKSEL PORTA           ;Banco 0
                    btfss    STATUS,Z        ;Es la 1ª vez que se usa la EEPROM ??
                    goto    Inicializado            ;No, el sistema ya se ha usado.
                    clrf    contador

; ###############################################################################

; Bucle principal
                    BANKSEL OSCCON
                    movlw   b'01100000'     ; 4 MHz
                    movwf   OSCCON
                    banksel PORTA           ; bank 0, siempre
                    goto Inicializado
Principal:
                    movf    PORTA, w        ; leer puerto A
                    andlw   PORTA_ES        ; nos quedamos sólo con lo interesante

                    btfss   STATUS, Z       ; ¿Se ha pulsado? Lo está si RA4 == 0
                    goto    Principal       ; No, esperar
;
; Aquí llegamos con el botón pulsado
Inicializado:
                    call    incrementa_contador
                    call    visualiza_contador
                    call    salida_hacia_A

; Esperamos que levante el botón
Espera_levantar:
                    call    Retardo_100ms   ; Esperar la suelta del pulsador
                    movf    PORTA, w        ; leer puerto A
                    andlw   PORTA_ES        ; nos quedamos sólo con lo interesante
                    btfsc   STATUS, Z       ; ¿Sigue pulsado? Lo está si RA4 == 0
                    goto    Espera_levantar ; No, esperar
;
                    goto    Principal


; ******************************************************************************
;; salida_hacia_A
;
; Según el valor del contador ([1-4]), lo transforma en otro, basado en una
; tabla y lo saca por el puerto A
;

salida_hacia_A:     call    transforma_contador
                    movwf   PORTA           ; visualiza en puerto A
                    return

transforma_contador:
                    decf    contador,w      ; leemos el contador y le restamos 1
                    addwf   PCL, f          ; saltamos dentro de la tabla

;                            |76543210|
                    retlw   b'00000010'
                    retlw   b'00000101'
                    retlw   b'00000110'
                    retlw   b'00001001'

; ******************************************************************************
;; incrementa_contador
;
; Incrementa el valor de la variable contador, entre 1 y 4, inclusives.
;

incrementa_contador:
                    bcf     contador,2
                    incf    contador
                    call    Escribir_EEPROM ; Escribir dato en la EEPROM.
                    return

; ******************************************************************************
;; visualiza_contador
;
; Muestra el valor del contador en el display de 7 segmentos
;

visualiza_contador:
                    movfw   contador        ; leemos contador
                    call    w_a_digito      ; transformación a dígito 7 segmentos
                    movwf   PORTB           ; visualiza en puerto B
                    return

w_a_digito:         addwf   PCL, f          ; salta al dígito indexado por w

;                            |76543210|
                    retlw   b'00111111'     ; 0
                    retlw   b'00000110'     ; 1
                    retlw   b'01011011'     ; 2
                    retlw   b'01001111'     ; 3
                    retlw   b'01100110'     ; 4
                    retlw   b'01101101'     ; 5
                    retlw   b'01111101'     ; 6
                    retlw   b'00000111'     ; 7
                    retlw   b'01111111'     ; 8
                    retlw   b'01101111'     ; 9

; ----------------------------------------------------------------------------------------------------
; Espera = 100ms
; Frecuencia de reloj = 4Mhz
;
; Espera real = 0.1 segundos = 100000 ciclos
; Error = 0.00 %

Retardo_par:        udata_shr

Retardo_100ms_d1    res 1
Retardo_100ms_d2    res 1


Retardo_code:       code

Retardo_100ms:
                                    ;99993 ciclos
                    movlw   0x1E
                    movwf   Retardo_100ms_d1
                    movlw   0x4F
                    movwf   Retardo_100ms_d2

Retardo_100ms_loop:
                    decfsz  Retardo_100ms_d1, f
                    goto    $+2
                    decfsz  Retardo_100ms_d2, f
                    goto    Retardo_100ms_loop

                                    ;3 ciclos
                    goto    $+1
                    nop

                                    ;4 ciclos (incluyendo la llamada)
                    return

; Generado por delay_pic.pl (Joaquín Ferrero. 2014.07.22)
; ./delay_pic.pl -s Retardo_100ms 4Mhz 100ms
; mar 22 jul 2014 19:22:23 CEST
; http://perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
; ----------------------------------------------------------------------------------------------------

; ******************************************************************************

;Subrutinas EEPROM -----------------------------------------------------------

Leer_EEPROM
    BANKSEL EEADR           ; Selecciona el registro EEADR.
    movf    contador, W
    movwf   EEADR           ; Dato dirección de momoria a leer.
    BANKSEL EECON1          ; Selecciona el banco EECON1.
    bcf     EECON1, EEPGD    ; Punto a memoria de datos
    bsf     EECON1, RD      ; a Leer.
    BANKSEL EEDATA          ; Seleccionar banco de EEDATA.
    movf    EEDATA, W       ; W = EEDATA.
    BANKSEL PORTA
    return

Escribir_EEPROM
    BANKSEL EECON1          ; Selecciona banco de EECON1.
    btfsc   EECON1, WR      ; Espera para escribir
    goto    $-1             ; a completar.
    BANKSEL EEADR           ; Selecciona el banco EEADR.
    movf    contador, W
    movwf   EEADR           ; Dirección dato de memoria a escribir.
    BANKSEL EECON1          ; Selecciona el banco EECOn1.
    bcf     EECON1, EEPGD   ; Punto a dato de memoria.
    bsf     EECON1, WREN    ; Activar escritura.
    bcf     INTCON, GIE     ; Desactiva interrupciones.

; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROm.

    movlw   0x55
    movwf   EECON2          ; Escribe 55h.
    movlw   0xAA
    movwf   EECON2          ; Escribe AAh.
    bsf     EECON1, WR

    bsf     INTCON, GIE     ; Activa interrupciones.
    bcf     EECON1, WREN    ; Desactiva escrituras.
    BANKSEL PORTA
    return

                END
 
#29
Cuidado... estás usando como dirección de la EEPROM el valor que contiene contador... así que estás escribiendo/leyendo en las direcciones 1 a 4, no en una dirección fija.

A mi esto me funciona:
PHP:
;
; Un pulsador en RA4 va incrementando un contador, entre [1-4].
; La salida se envía a un display de 7 seg. en PORTB, y hacia salidas en PORTA.
; El contador queda guardado en la EEPROM.
;
; (Contador)  |RB 76543210 |RA 76543210
; ------------|------------------------
;       1     |   00000011 |   00000010
;       2     |   00100100 |   00000101
;       3     |   00001100 |   00000110
;       4     |   00111100 |   00001001
;
; PORTA:
;  RA0 : OE1
;  RA1 : OE2
;  RA2 : A21
;  RA3 : AUX
;  RA4 : Pulsador
;
; PORTB : display de 7 segmentos. a = RB0
;

;*******************************************************************************
; Listado y condiciones de ensamblado

                    processor   16F88           ; 4 Mhz
                    radix       dec
                    errorlevel  -302            ; Turn off banking message

;*******************************************************************************
; Bibliotecas

                    include p16f88.inc

;*******************************************************************************
; Fusibles

  __CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO

; _CP_OFF           : Protección de código
; _DEBUG_OFF        : Debug en circuito
; _WRT_PROTECT_OFF  : Protección a escritura en memoria de programa
; _CPD_OFF          : Protección de código de datos
; _LVP_OFF          : Programación en baja tensión
; _BODEN_OFF        : Reset por Brown-out
; _MCLRE_ON         : Reset por pin externo
; _PWRTE_ON         : Retraso al reset
; _WDT_OFF          : Watchdog
; _XT_OSC           : Oscilador externo del tipo XT


;*******************************************************************************
; Definiciones

; Máscaras de E/S de los puertos. 0 = salida, 1 = entrada
;                    |76543210|
#define PORTA_IO    b'00010000'
#define PORTB_IO    b'00000000'

; Incorporar sentencias de comprobación de la EEPROM
#define test_eeprom 0

;*******************************************************************************
; Variables
                    udata_shr

contador            res 1                   ; contador en la SRAM

; ******************************************************************************
; EEPROM

; Dirección del contador dentro de la EEPROM
ee_contador:        equ     0x02

; Debemos desplazarnos a la zona de memoria más allá del 0x2100, que corresponde
; a la zona de la EEPROM en la mayoría de los PIC (ver documentación).
; Este valor es el que se grabará en la EEPROM en el momento de grabar el programa
; en el µcontrolador.
                    org     0x2100 + ee_contador

                    de      1               ; valor inicial de ee_contador

;*******************************************************************************

                    code    0x0000

_Start:
                    banksel ANSEL           ; bank 1
                    clrf    ANSEL           ; puerto A digital
                    movlw   PORTA_IO        ; definir E/S puerto A
                    movwf   TRISA
                    movlw   PORTB_IO        ; definir E/S puerto B
                    movwf   TRISB
                    movlw   b'01100000'     ; 4 MHz
                    movwf   OSCCON

; Leer valor del contador en la EEPROM
                    banksel EEADR           ; bank 2
                    movlw   ee_contador     ; dirección de la EEPROM a leer
                    movwf   EEADR

                    banksel EECON1          ; bank 3
                    bcf     EECON1, EEPGD   ; acceso a la memoria de datos
                    bsf     EECON1, RD      ; inicia la lectura

                    banksel EEDATA          ; bank 2
                    movf    EEDATA, w       ; dato leído en W
                    movwf   contador        ; guardar en SRAM
;
                    banksel PORTA           ; bank 0, durante el programa

#if test_eeprom
; Comprobar que el contador es correcto (esta parte es opcional)
                    decf    contador, w     ; leemos el contador y le quitamos 1
                    andlw   0x3             ; nos quedamos solo con los bits inferiores
                    addlw   0x1             ; volvemos a sumarle 1
                    movwf   contador        ; y lo guardamos
#endif
                    goto    Visualiza       ; ir a presentar

; Bucle principal
Principal:          btfsc   PORTA, RA4      ; leer pulsador
                    goto    Principal       ; No, esperar
;
; Se ha pulsado el botón
                    call    incrementa_contador
Visualiza:          call    visualiza_contador
                    call    salida_hacia_A

; Esperar liberación del botón
Espera_levantar:    call    Retardo_100ms   ; Esperar la suelta del botón

                    btfss   PORTA, RA4      ; leer pulsador
                    goto    Espera_levantar ; No, esperar

; Repetir
                    goto    Principal


; ******************************************************************************
;; salida_hacia_A
;
; Según el valor del contador ([1-4]), lo transforma en otro, basado en una
; tabla y lo saca por el puerto A
;

salida_hacia_A:     call    transforma_contador
                    movwf   PORTA           ; visualiza en puerto A
                    return

transforma_contador:
                    decf    contador, w     ; leemos el contador y le restamos 1
                    addwf   PCL, f          ; saltamos dentro de la tabla

;                            |76543210|
                    retlw   b'00000010'
                    retlw   b'00000101'
                    retlw   b'00000110'
                    retlw   b'00001001'

; ******************************************************************************
;; incrementa_contador
;
; Incrementa el valor de la variable contador, entre 1 y 4, inclusives.
;

incrementa_contador:
                    bcf     contador, 2     ; Si el contador valía 4, ahora vale 0
                    incf    contador, f     ; Incrementa el contador

; Escribe el contador en la EEPROM
                    banksel EECON1          ; bank 3
                    btfsc   EECON1, WR      ; esperar para poder escribir
                    goto    $-1

                    banksel EEADR           ; bank 2
                    movlw   ee_contador     ; dirección donde vamos a escribir
                    movwf   EEADR

                    movf    contador, w     ; el valor que vamos a escribir
                    movwf   EEDATA

                    banksel EECON1          ; bank 3
                    bcf     EECON1, EEPGD   ; acceso a la memoria de datos
                    bsf     EECON1, WREN    ; activa la escritura

;                    bcf     INTCON, GIE     ; desactivar interrupciones

                    movlw   b'01010101'     ; valores mágicos (requeridos)
                    movwf   EECON2
                    movlw   b'10101010'
                    movwf   EECON2

                    bsf     EECON1, WR      ; comienza la escritura

;                    bsf     INTCON, GIE     ; reactiva interrupciones

                    bcf     EECON1, WREN    ; desactiva escrituras

                    banksel PORTA           ; volvemos a bank 0
                    return

; ******************************************************************************
;; visualiza_contador
;
; Muestra el valor del contador en el display de 7 segmentos
;

visualiza_contador:
                    movfw   contador        ; leemos contador
                    call    w_a_digito      ; transformación a dígito 7 segmentos
                    movwf   PORTB           ; visualiza en puerto B
                    return

w_a_digito:         addwf   PCL, f          ; salta al dígito indexado por w

;                            |76543210|
                    retlw   b'00111111'     ; 0
                    retlw   b'00000110'     ; 1
                    retlw   b'01011011'     ; 2
                    retlw   b'01001111'     ; 3
                    retlw   b'01100110'     ; 4
                    retlw   b'01101101'     ; 5
                    retlw   b'01111101'     ; 6
                    retlw   b'00000111'     ; 7
                    retlw   b'01111111'     ; 8
                    retlw   b'01101111'     ; 9

; ----------------------------------------------------------------------------------------------------
; Espera = 100ms
; Frecuencia de reloj = 4Mhz
;
; Espera real = 0.1 segundos = 100000 ciclos
; Error = 0.00 %

Retardo_var:        udata_shr

Retardo_100ms_d1    res 1
Retardo_100ms_d2    res 1

Retardo_code:       code

Retardo_100ms:
                                    ;99993 ciclos
                    movlw   0x1E
                    movwf   Retardo_100ms_d1
                    movlw   0x4F
                    movwf   Retardo_100ms_d2

Retardo_100ms_loop:
                    decfsz  Retardo_100ms_d1, f
                    goto    $+2
                    decfsz  Retardo_100ms_d2, f
                    goto    Retardo_100ms_loop

                                    ;3 ciclos
                    goto    $+1
                    nop

                                    ;4 ciclos (incluyendo la llamada)
                    return

; Generado por delay_pic.pl (Joaquín Ferrero. 2014.07.22)
; ./delay_pic.pl -s Retardo_100ms 4Mhz 100ms
; mar 22 jul 2014 19:22:23 CEST
; http://perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
; ----------------------------------------------------------------------------------------------------

; ******************************************************************************


                    end
Con la ayuda de 'de' inicializamos el valor de la posición 0x02 de la EEPROM a '1' (según el mapa de memoria, esa dirección de EEPROM corresponde a la 0x2102 en la mayor parte de los PIC 1x -no de los PIC 18- Ver más información sobre 'de' en el manual del ensamblador MPASM). Ese valor es el que se graba en el momento de grabar el programa en el µcontrolador, como valor inicial.

Después de inicializar el µcontrolador, leemos la EEPROM. Luego comprobamos que el valor esté realmente entre los valores que queremos (1 a 4) (esta parte es opcional y la controla un #define).

Y luego sigue todo lo demás.

Un detalle, que he dejado comentado, son las líneas que activan y desactivan las interrupciones, en la parte de la escritura en la EEPROM, porque este programa no tiene interrupciones definidas (al menos de momento).

Además, he simplificado la forma de leer el botón.
 
Última edición:
#30
Cuidado... estás usando como dirección de la EEPROM el valor que contiene contador... así que estás escribiendo/leyendo en las direcciones 1 a 4, no en una dirección fija.

A mi esto me funciona:
PHP:
;
; Un pulsador en RA4 va incrementando un contador, entre [1-4].
; La salida se envía a un display de 7 seg. en PORTB, y hacia salidas en PORTA.
; El contador queda guardado en la EEPROM.
;
; (Contador)  |RB 76543210 |RA 76543210
; ------------|------------------------
;       1     |   00000011 |   00000010
;       2     |   00100100 |   00000101
;       3     |   00001100 |   00000110
;       4     |   00111100 |   00001001
;
; PORTA:
;  RA0 : OE1
;  RA1 : OE2
;  RA2 : A21
;  RA3 : AUX
;  RA4 : Pulsador
;
; PORTB : display de 7 segmentos. a = RB0
;

;*******************************************************************************
; Listado y condiciones de ensamblado

                    processor   16F88           ; 4 Mhz
                    radix       dec
                    errorlevel  -302            ; Turn off banking message

;*******************************************************************************
; Bibliotecas

                    include p16f88.inc

;*******************************************************************************
; Fusibles

  __CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO

; _CP_OFF           : Protección de código
; _DEBUG_OFF        : Debug en circuito
; _WRT_PROTECT_OFF  : Protección a escritura en memoria de programa
; _CPD_OFF          : Protección de código de datos
; _LVP_OFF          : Programación en baja tensión
; _BODEN_OFF        : Reset por Brown-out
; _MCLRE_ON         : Reset por pin externo
; _PWRTE_ON         : Retraso al reset
; _WDT_OFF          : Watchdog
; _XT_OSC           : Oscilador externo del tipo XT


;*******************************************************************************
; Definiciones

; Máscaras de E/S de los puertos. 0 = salida, 1 = entrada
;                    |76543210|
#define PORTA_IO    b'00010000'
#define PORTB_IO    b'00000000'

; Incorporar sentencias de comprobación de la EEPROM
#define test_eeprom 0

;*******************************************************************************
; Variables
                    udata_shr

contador            res 1                   ; contador en la SRAM

; ******************************************************************************
; EEPROM

; Dirección del contador dentro de la EEPROM
ee_contador:        equ     0x02

; Debemos desplazarnos a la zona de memoria más allá del 0x2100, que corresponde
; a la zona de la EEPROM en la mayoría de los PIC (ver documentación).
; Este valor es el que se grabará en la EEPROM en el momento de grabar el programa
; en el µcontrolador.
                    org     0x2100 + ee_contador

                    de      1               ; valor inicial de ee_contador

;*******************************************************************************

                    code    0x0000

_Start:
                    banksel ANSEL           ; bank 1
                    clrf    ANSEL           ; puerto A digital
                    movlw   PORTA_IO        ; definir E/S puerto A
                    movwf   TRISA
                    movlw   PORTB_IO        ; definir E/S puerto B
                    movwf   TRISB
                    movlw   b'01100000'     ; 4 MHz
                    movwf   OSCCON

; Leer valor del contador en la EEPROM
                    banksel EEADR           ; bank 2
                    movlw   ee_contador     ; dirección de la EEPROM a leer
                    movwf   EEADR

                    banksel EECON1          ; bank 3
                    bcf     EECON1, EEPGD   ; acceso a la memoria de datos
                    bsf     EECON1, RD      ; inicia la lectura

                    banksel EEDATA          ; bank 2
                    movf    EEDATA, w       ; dato leído en W
                    movwf   contador        ; guardar en SRAM
;
                    banksel PORTA           ; bank 0, durante el programa

#if test_eeprom
; Comprobar que el contador es correcto (esta parte es opcional)
                    decf    contador, w     ; leemos el contador y le quitamos 1
                    andlw   0x3             ; nos quedamos solo con los bits inferiores
                    addlw   0x1             ; volvemos a sumarle 1
                    movwf   contador        ; y lo guardamos
#endif
                    goto    Visualiza       ; ir a presentar

; Bucle principal
Principal:          btfsc   PORTA, RA4      ; leer pulsador
                    goto    Principal       ; No, esperar
;
; Se ha pulsado el botón
                    call    incrementa_contador
Visualiza:          call    visualiza_contador
                    call    salida_hacia_A

; Esperar liberación del botón
Espera_levantar:    call    Retardo_100ms   ; Esperar la suelta del botón

                    btfss   PORTA, RA4      ; leer pulsador
                    goto    Espera_levantar ; No, esperar

; Repetir
                    goto    Principal


; ******************************************************************************
;; salida_hacia_A
;
; Según el valor del contador ([1-4]), lo transforma en otro, basado en una
; tabla y lo saca por el puerto A
;

salida_hacia_A:     call    transforma_contador
                    movwf   PORTA           ; visualiza en puerto A
                    return

transforma_contador:
                    decf    contador, w     ; leemos el contador y le restamos 1
                    addwf   PCL, f          ; saltamos dentro de la tabla

;                            |76543210|
                    retlw   b'00000010'
                    retlw   b'00000101'
                    retlw   b'00000110'
                    retlw   b'00001001'

; ******************************************************************************
;; incrementa_contador
;
; Incrementa el valor de la variable contador, entre 1 y 4, inclusives.
;

incrementa_contador:
                    bcf     contador, 2     ; Si el contador valía 4, ahora vale 0
                    incf    contador, f     ; Incrementa el contador

; Escribe el contador en la EEPROM
                    banksel EECON1          ; bank 3
                    btfsc   EECON1, WR      ; esperar para poder escribir
                    goto    $-1

                    banksel EEADR           ; bank 2
                    movlw   ee_contador     ; dirección donde vamos a escribir
                    movwf   EEADR

                    movf    contador, w     ; el valor que vamos a escribir
                    movwf   EEDATA

                    banksel EECON1          ; bank 3
                    bcf     EECON1, EEPGD   ; acceso a la memoria de datos
                    bsf     EECON1, WREN    ; activa la escritura

;                    bcf     INTCON, GIE     ; desactivar interrupciones

                    movlw   b'01010101'     ; valores mágicos (requeridos)
                    movwf   EECON2
                    movlw   b'10101010'
                    movwf   EECON2

                    bsf     EECON1, WR      ; comienza la escritura

;                    bsf     INTCON, GIE     ; reactiva interrupciones

                    bcf     EECON1, WREN    ; desactiva escrituras

                    banksel PORTA           ; volvemos a bank 0
                    return

; ******************************************************************************
;; visualiza_contador
;
; Muestra el valor del contador en el display de 7 segmentos
;

visualiza_contador:
                    movfw   contador        ; leemos contador
                    call    w_a_digito      ; transformación a dígito 7 segmentos
                    movwf   PORTB           ; visualiza en puerto B
                    return

w_a_digito:         addwf   PCL, f          ; salta al dígito indexado por w

;                            |76543210|
                    retlw   b'00111111'     ; 0
                    retlw   b'00000110'     ; 1
                    retlw   b'01011011'     ; 2
                    retlw   b'01001111'     ; 3
                    retlw   b'01100110'     ; 4
                    retlw   b'01101101'     ; 5
                    retlw   b'01111101'     ; 6
                    retlw   b'00000111'     ; 7
                    retlw   b'01111111'     ; 8
                    retlw   b'01101111'     ; 9

; ----------------------------------------------------------------------------------------------------
; Espera = 100ms
; Frecuencia de reloj = 4Mhz
;
; Espera real = 0.1 segundos = 100000 ciclos
; Error = 0.00 %

Retardo_var:        udata_shr

Retardo_100ms_d1    res 1
Retardo_100ms_d2    res 1

Retardo_code:       code

Retardo_100ms:
                                    ;99993 ciclos
                    movlw   0x1E
                    movwf   Retardo_100ms_d1
                    movlw   0x4F
                    movwf   Retardo_100ms_d2

Retardo_100ms_loop:
                    decfsz  Retardo_100ms_d1, f
                    goto    $+2
                    decfsz  Retardo_100ms_d2, f
                    goto    Retardo_100ms_loop

                                    ;3 ciclos
                    goto    $+1
                    nop

                                    ;4 ciclos (incluyendo la llamada)
                    return

; Generado por delay_pic.pl (Joaquín Ferrero. 2014.07.22)
; ./delay_pic.pl -s Retardo_100ms 4Mhz 100ms
; mar 22 jul 2014 19:22:23 CEST
; http://perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
; ----------------------------------------------------------------------------------------------------

; ******************************************************************************


                    end
Muchas gracias por el código, lo he probado y funciona.

Con la ayuda de 'de' inicializamos el valor de la posición 0x02 de la EEPROM a '1' (según el mapa de memoria, esa dirección de EEPROM corresponde a la 0x2102 en la mayor parte de los PIC 1x -no de los PIC 18- Ver más información sobre 'de' en el manual del ensamblador MPASM). Ese valor es el que se graba en el momento de grabar el programa en el µcontrolador, como valor inicial.

En libros en español e incluso en el datasheet del PIC16F88, no he encontrado esa información que debo ponerlo en dos direcciones más adelante. Con razón que me volvía loco de la cabeza.


Después de inicializar el µcontrolador, leemos la EEPROM. Luego comprobamos que el valor esté realmente entre los valores que queremos (1 a 4) (esta parte es opcional y la controla un #define).

Y luego sigue todo lo demás.

Un detalle, que he dejado comentado, son las líneas que activan y desactivan las interrupciones, en la parte de la escritura en la EEPROM, porque este programa no tiene interrupciones definidas (al menos de momento).

Entendido y es verdad.

Además, he simplificado la forma de leer el botón.
Gracias por todo, aún así buscaré información sobre este tema, sobre todo en MPASM.


;)
 
#31
Ya veo que funciona, y muy bien ;)

La información sobre lo de usar 'de' la encontré por pura casualidad :) Es la página 96 del documento "mpasmx/Docs/MPASM_MPLINK_User_Guide.pdf" (DS33014L). Busqué por la palabra EEPROM en el documento, para ver si ponía algún ejemplo de cómo hacer la lectura/escritura, y salió eso, así que lo agregué al programa.

Se trata de una característica propia del ensamblador, y sólo para inicializar la EEPROM en el momento de la grabación del programa. Si no se va a grabar nada en la EEPROM, al principio, pues no hace falta.

En el caso del compilador XC8 de MPLAB, se hace con la macro __EEPROM_DATA() o el cualificador __eeprom.
 
#32
Lo tendré que leer más a fondo.

Una cosa que no entiendo lo que hiciste aquí.

Código:
#if test_eeprom
; Comprobar que el contador es correcto (esta parte es opcional)
                    decf    contador, w     ; leemos el contador y le quitamos 1
                    andlw   0x3             ; nos quedamos solo con los bits inferiores
                    addlw   0x1             ; volvemos a sumarle 1
                    movwf   contador        ; y lo guardamos
#endif
                    goto    Visualiza       ; ir a presentar
Está claro que es para comprobar, pero hay un pero en las EEPROM, que duran un tiempo. Si pasa esos ciclos que creo que eran unos mil, esa zona de memoria dejará de funcionar.

Saludo.
 
#33
La presencia de esas cuatro líneas en el ensamblado del programa depende del valor que tenga el #define del símbolo test_eeprom (unas líneas más arriba). Por defecto, lo he dejado en 0, para no incluirlas, ya que se supone que el 'de' va a funcionar y el programador del PIC va a grabar el valor inicial del contador en la memoria EEPROM.

Y no sé dónde has leído eso de la memoria EEPROM, pero según la página 3 (page 1) del datasheet del PIC16F88, esa memoria aguanta 1 millón de ciclos de lectura/escritura, y los datos guardados pueden mantenerse (es decir, sin alimentación) durante ¡más de 40 años!
 
#34
Cierto.

Por cierto.
Cuando pones etiquetas como esta incrementa_contador:
es decir, con : al final. En realidad no hace falta.

¿Es una ventaja poner : al final de la etiqueta que cuando no los tiene?

Otra curisosidad. En la variables o variables RES 1, me quita una pocisión de memoria, si pongo RES 15 me quita 15. Si solo uso un byte, a pesar de usar 15 como reserva, queda como ocupada los 15 byte.

¿Qué utilidad tiene realmente?

A mi me funciona igual.
 
Última edición:
#35
Con el ensamblador de MPASM, no, no hay ventaja. Se pueden poner o no.

Si los pongo es simplemente por costumbre: muchos otros lenguajes ensambladores sí que lo necesitan. Incluso el conocido ensamblador ASxxxx usa el '::' para declarar la etiqueta como global.

Otra cosilla... en el código dejé 0x02 como dirección de ee_contador, pero podría haber sido cualquier otra, en el rango 0x00 a 0xFF.
 
Última edición:
#37
Pues no, puedes elegir la dirección que quieras. Revisa la página 96 indicada antes, donde se describe 'de', y verás que te explica lo del desplazamiento 0x2100, para referirnos a la EE_PROM.

Lo de dejarlo en 0x02 es porque estuve haciendo pruebas con el depurador del MPASM, ejecutando el programa paso a paso, para ver qué hacía, y es ahí donde me di cuenta del fallo gordo que había en los primeras versiones del programa. Estaba usando

movf ee_contador, w ; mover el contenido de ee_contador a w

en lugar de lo correcto, que es

movlw ee_contador ; mover la dirección de ee_contador a w

Vamos, que estaba confundiendo el contenido con la dirección del contenido.

Hasta que no ejecutas el programa paso a paso, con el depurador del MPASM no te das cuenta de estas cosas :)

Otra cosilla... acabo de darme cuenta que el mnemónico movfw realmente es una pseudo-instrucción, y Microchip recomienda no usarla, así que la línea

movfw contador ; leemos contador

se debe cambiar a

movf contador,w ; leemos contador
 
Última edición:
#39
Buenas:

Voy hacerles una pregunta. Sobre el código de arriba quiero hacer algo parecido del PIC16F88 al PIC16F630 para saber si realmente funciona. Hablo de adaptación del código y usando un decodificador 74LS48.

Transformar este esquema...


Con este otro.

Habiendo el primer circuito con menos componentes. ¿Por qué usar el segundo esquema también?

Porque otras personas que quieren montar el circuito no pueden debido a que su local de electrónica favorita no tienen el PIC16F88 y si el PIC16F630 junto con el decodificador de 7 segmentos 74LS48.

Partiendo del código de abajo del PIC16F88 para analizarlo bien.
Código:
[COLOR=#007700];
; [COLOR=#0000BB]Un pulsador en RA4 va incrementando un contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]entre [/COLOR][COLOR=#007700][[/COLOR][COLOR=#0000BB]1[/COLOR][COLOR=#007700]-[/COLOR][COLOR=#0000BB]4[/COLOR][COLOR=#007700]].
; [/COLOR][COLOR=#0000BB]La salida se envía a un display de 7 seg[/COLOR][COLOR=#007700]. [/COLOR][COLOR=#0000BB]en PORTB[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]y hacia salidas en PORTA[/COLOR][COLOR=#007700].
; [/COLOR][COLOR=#0000BB]El contador queda guardado en la EEPROM[/COLOR][COLOR=#007700].
;
; ([/COLOR][COLOR=#0000BB]Contador[/COLOR][COLOR=#007700])  |[/COLOR][COLOR=#0000BB]RB 76543210 [/COLOR][COLOR=#007700]|[/COLOR][COLOR=#0000BB]RA 76543210
[/COLOR][COLOR=#007700]; ------------|------------------------
;       [/COLOR][COLOR=#0000BB]1     [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00000011 [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00000010
[/COLOR][COLOR=#007700];       [/COLOR][COLOR=#0000BB]2     [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00100100 [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00000101
[/COLOR][COLOR=#007700];       [/COLOR][COLOR=#0000BB]3     [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00001100 [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00000110
[/COLOR][COLOR=#007700];       [/COLOR][COLOR=#0000BB]4     [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00111100 [/COLOR][COLOR=#007700]|   [/COLOR][COLOR=#0000BB]00001001
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]PORTA[/COLOR][COLOR=#007700]:
;  [/COLOR][COLOR=#0000BB]RA0 [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]OE1
[/COLOR][COLOR=#007700];  [/COLOR][COLOR=#0000BB]RA1 [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]OE2
[/COLOR][COLOR=#007700];  [/COLOR][COLOR=#0000BB]RA2 [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]A21
[/COLOR][COLOR=#007700];  [/COLOR][COLOR=#0000BB]RA3 [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]AUX
[/COLOR][COLOR=#007700];  [/COLOR][COLOR=#0000BB]RA4 [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Pulsador
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]PORTB [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]display de 7 segmentos[/COLOR][COLOR=#007700]. [/COLOR][COLOR=#0000BB]a [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]RB0
[/COLOR][COLOR=#007700];

;*******************************************************************************
; [/COLOR][COLOR=#0000BB]Listado y condiciones de ensamblado

                    processor   16F88           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]4 Mhz
                    radix       dec
                    errorlevel  [/COLOR][COLOR=#007700]-[/COLOR][COLOR=#0000BB]302            [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Turn off banking message

[/COLOR][COLOR=#007700];*******************************************************************************
; [/COLOR][COLOR=#0000BB]Bibliotecas

                    [/COLOR][COLOR=#007700]include [/COLOR][COLOR=#0000BB]p16f88[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000BB]inc

[/COLOR][COLOR=#007700];*******************************************************************************
; [/COLOR][COLOR=#0000BB]Fusibles

  __CONFIG _CONFIG1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]_CP_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_DEBUG_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_WRT_PROTECT_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_CPD_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_LVP_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_BODEN_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_MCLR_ON [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_PWRTE_ON [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_WDT_OFF [/COLOR][COLOR=#007700]& [/COLOR][COLOR=#0000BB]_INTRC_IO

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_CP_OFF           [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Protección de código
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_DEBUG_OFF        [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Debug en circuito
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_WRT_PROTECT_OFF  [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Protección a escritura en memoria de programa
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_CPD_OFF          [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Protección de código de datos
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_LVP_OFF          [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Programación en baja tensión
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_BODEN_OFF        [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Reset por Brown[/COLOR][COLOR=#007700]-[/COLOR][COLOR=#0000BB]out
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_MCLRE_ON         [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Reset por pin externo
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_PWRTE_ON         [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Retraso al reset
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_WDT_OFF          [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Watchdog
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]_XT_OSC           [/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000BB]Oscilador externo del tipo XT


[/COLOR][COLOR=#007700];*******************************************************************************
; [/COLOR][COLOR=#0000BB]Definiciones

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Máscaras de E[/COLOR][COLOR=#007700]/[/COLOR][COLOR=#0000BB]S de los puertos[/COLOR][COLOR=#007700]. [/COLOR][COLOR=#0000BB]0 [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]salida[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]1 [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]entrada
[/COLOR][COLOR=#007700];                    |[/COLOR][COLOR=#0000BB]76543210[/COLOR][COLOR=#007700]|
[/COLOR][COLOR=#FF8000]#define PORTA_IO    b'00010000'
#define PORTB_IO    b'00000000'

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Incorporar sentencias de comprobación de la EEPROM
[/COLOR][COLOR=#FF8000]#define test_eeprom 0

[/COLOR][COLOR=#007700];*******************************************************************************
; [/COLOR][COLOR=#0000BB]Variables
                    udata_shr

contador            res 1                   [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]contador en la SRAM

[/COLOR][COLOR=#007700]; ******************************************************************************
; [/COLOR][COLOR=#0000BB]EEPROM

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Dirección del contador dentro de la EEPROM
ee_contador[/COLOR][COLOR=#007700]:        [/COLOR][COLOR=#0000BB]equ     0x02

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Debemos desplazarnos a la zona de memoria más allá del 0x2100[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]que corresponde
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]a la zona de la EEPROM en la mayoría de los PIC [/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]ver documentación[/COLOR][COLOR=#007700]).
; [/COLOR][COLOR=#0000BB]Este valor es el que se grabará en la EEPROM en el momento de grabar el programa
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]en el µcontrolador[/COLOR][COLOR=#007700].
                    [/COLOR][COLOR=#0000BB]org     0x2100 [/COLOR][COLOR=#007700]+ [/COLOR][COLOR=#0000BB]ee_contador

                    de      1               [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]valor inicial de ee_contador

[/COLOR][COLOR=#007700];*******************************************************************************

                    [/COLOR][COLOR=#0000BB]code    0x0000

_Start[/COLOR][COLOR=#007700]:
                    [/COLOR][COLOR=#0000BB]banksel ANSEL           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 1
                    clrf    ANSEL           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]puerto A digital
                    movlw   PORTA_IO        [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]definir E[/COLOR][COLOR=#007700]/[/COLOR][COLOR=#0000BB]S puerto A
                    movwf   TRISA
                    movlw   PORTB_IO        [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]definir E[/COLOR][COLOR=#007700]/[/COLOR][COLOR=#0000BB]S puerto B
                    movwf   TRISB
                    movlw   [/COLOR][COLOR=#DD0000]b'01100000'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]4 MHz
                    movwf   OSCCON

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Leer valor del contador en la EEPROM
                    banksel EEADR           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 2
                    movlw   ee_contador     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]dirección de la EEPROM a leer
                    movwf   EEADR

                    banksel EECON1          [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 3
                    bcf     EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]EEPGD   [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]acceso a la memoria de datos
                    bsf     EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]RD      [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]inicia la lectura

                    banksel EEDATA          [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 2
                    movf    EEDATA[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]w       [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]dato leído en W
                    movwf   contador        [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]guardar en SRAM
[/COLOR][COLOR=#007700];
                    [/COLOR][COLOR=#0000BB]banksel PORTA           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 0[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]durante el programa

[/COLOR][COLOR=#FF8000]#if test_eeprom
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Comprobar que el contador es correcto [/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]esta parte es opcional[/COLOR][COLOR=#007700])
                    [/COLOR][COLOR=#0000BB]decf    contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]w     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]leemos el contador y le quitamos 1
                    andlw   0x3             [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]nos quedamos solo con los bits inferiores
                    addlw   0x1             [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]volvemos a sumarle 1
                    movwf   contador        [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]y lo guardamos
[/COLOR][COLOR=#FF8000]#endif
                    [/COLOR][COLOR=#007700]goto    [/COLOR][COLOR=#0000BB]Visualiza       [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]ir a presentar

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Bucle principal
Principal[/COLOR][COLOR=#007700]:          [/COLOR][COLOR=#0000BB]btfsc   PORTA[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]RA4      [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]leer pulsador
                    [/COLOR][COLOR=#007700]goto    [/COLOR][COLOR=#0000BB]Principal       [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]No[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]esperar
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]Se ha pulsado el botón
                    call    incrementa_contador
Visualiza[/COLOR][COLOR=#007700]:          [/COLOR][COLOR=#0000BB]call    visualiza_contador
                    call    salida_hacia_A

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Esperar liberación del botón
Espera_levantar[/COLOR][COLOR=#007700]:    [/COLOR][COLOR=#0000BB]call    Retardo_100ms   [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Esperar la suelta del botón

                    btfss   PORTA[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]RA4      [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]leer pulsador
                    [/COLOR][COLOR=#007700]goto    [/COLOR][COLOR=#0000BB]Espera_levantar [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]No[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]esperar

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Repetir
                    [/COLOR][COLOR=#007700]goto    [/COLOR][COLOR=#0000BB]Principal


[/COLOR][COLOR=#007700]; ******************************************************************************
;; [/COLOR][COLOR=#0000BB]salida_hacia_A
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]Según el valor del contador [/COLOR][COLOR=#007700]([[/COLOR][COLOR=#0000BB]1[/COLOR][COLOR=#007700]-[/COLOR][COLOR=#0000BB]4[/COLOR][COLOR=#007700]]), [/COLOR][COLOR=#0000BB]lo transforma en otro[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]basado en una
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]tabla y lo saca por el puerto A
[/COLOR][COLOR=#007700];

[/COLOR][COLOR=#0000BB]salida_hacia_A[/COLOR][COLOR=#007700]:     [/COLOR][COLOR=#0000BB]call    transforma_contador
                    movwf   PORTA           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]visualiza en puerto A
                    [/COLOR][COLOR=#007700]return

[/COLOR][COLOR=#0000BB]transforma_contador[/COLOR][COLOR=#007700]:
                    [/COLOR][COLOR=#0000BB]decf    contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]w     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]leemos el contador y le restamos 1
                    addwf   PCL[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]f          [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]saltamos dentro de la tabla

[/COLOR][COLOR=#007700];                            |[/COLOR][COLOR=#0000BB]76543210[/COLOR][COLOR=#007700]|
                    [/COLOR][COLOR=#0000BB]retlw   [/COLOR][COLOR=#DD0000]b'00000010'
                    [/COLOR][COLOR=#0000BB]retlw   [/COLOR][COLOR=#DD0000]b'00000101'
                    [/COLOR][COLOR=#0000BB]retlw   [/COLOR][COLOR=#DD0000]b'00000110'
                    [/COLOR][COLOR=#0000BB]retlw   [/COLOR][COLOR=#DD0000]b'00001001'

[/COLOR][COLOR=#007700]; ******************************************************************************
;; [/COLOR][COLOR=#0000BB]incrementa_contador
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]Incrementa el valor de la variable contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]entre 1 y 4[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]inclusives[/COLOR][COLOR=#007700].
;

[/COLOR][COLOR=#0000BB]incrementa_contador[/COLOR][COLOR=#007700]:
                    [/COLOR][COLOR=#0000BB]bcf     contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]2     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Si el contador valía 4[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]ahora vale 0
                    incf    contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]f     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Incrementa el contador

[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Escribe el contador en la EEPROM
                    banksel EECON1          [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 3
                    btfsc   EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]WR      [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]esperar para poder escribir
                    [/COLOR][COLOR=#007700]goto    $-[/COLOR][COLOR=#0000BB]1

                    banksel EEADR           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 2
                    movlw   ee_contador     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]dirección donde vamos a escribir
                    movwf   EEADR

                    movf    contador[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]w     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]el valor que vamos a escribir
                    movwf   EEDATA

                    banksel EECON1          [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]bank 3
                    bcf     EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]EEPGD   [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]acceso a la memoria de datos
                    bsf     EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]WREN    [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]activa la escritura

[/COLOR][COLOR=#007700];                    [/COLOR][COLOR=#0000BB]bcf     INTCON[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]GIE     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]desactivar interrupciones

                    movlw   [/COLOR][COLOR=#DD0000]b'01010101'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]valores mágicos [/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]requeridos[/COLOR][COLOR=#007700])
                    [/COLOR][COLOR=#0000BB]movwf   EECON2
                    movlw   [/COLOR][COLOR=#DD0000]b'10101010'
                    [/COLOR][COLOR=#0000BB]movwf   EECON2

                    bsf     EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]WR      [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]comienza la escritura

[/COLOR][COLOR=#007700];                    [/COLOR][COLOR=#0000BB]bsf     INTCON[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]GIE     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]reactiva interrupciones

                    bcf     EECON1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]WREN    [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]desactiva escrituras

                    banksel PORTA           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]volvemos a bank 0
                    [/COLOR][COLOR=#007700]return

; ******************************************************************************
;; [/COLOR][COLOR=#0000BB]visualiza_contador
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]Muestra el valor del contador en el display de 7 segmentos
[/COLOR][COLOR=#007700];

[/COLOR][COLOR=#0000BB]visualiza_contador[/COLOR][COLOR=#007700]:
                    [/COLOR][COLOR=#0000BB]movfw   contador        [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]leemos contador
                    call    w_a_digito      [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]transformación a dígito 7 segmentos
                    movwf   PORTB           [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]visualiza en puerto B
                    [/COLOR][COLOR=#007700]return

[/COLOR][COLOR=#0000BB]w_a_digito[/COLOR][COLOR=#007700]:         [/COLOR][COLOR=#0000BB]addwf   PCL[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]f          [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]salta al dígito indexado por w

[/COLOR][COLOR=#007700];                            |[/COLOR][COLOR=#0000BB]76543210[/COLOR][COLOR=#007700]|
                    [/COLOR][COLOR=#0000BB]retlw   [/COLOR][COLOR=#DD0000]b'00111111'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]0
                    retlw   [/COLOR][COLOR=#DD0000]b'00000110'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]1
                    retlw   [/COLOR][COLOR=#DD0000]b'01011011'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]2
                    retlw   [/COLOR][COLOR=#DD0000]b'01001111'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]3
                    retlw   [/COLOR][COLOR=#DD0000]b'01100110'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]4
                    retlw   [/COLOR][COLOR=#DD0000]b'01101101'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]5
                    retlw   [/COLOR][COLOR=#DD0000]b'01111101'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]6
                    retlw   [/COLOR][COLOR=#DD0000]b'00000111'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]7
                    retlw   [/COLOR][COLOR=#DD0000]b'01111111'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]8
                    retlw   [/COLOR][COLOR=#DD0000]b'01101111'     [/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]9

[/COLOR][COLOR=#007700]; ----------------------------------------------------------------------------------------------------
; [/COLOR][COLOR=#0000BB]Espera [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]100ms
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Frecuencia de reloj [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]4Mhz
[/COLOR][COLOR=#007700];
; [/COLOR][COLOR=#0000BB]Espera real [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]0.1 segundos [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]100000 ciclos
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]Error [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000BB]0.00 [/COLOR][COLOR=#007700]%

[/COLOR][COLOR=#0000BB]Retardo_var[/COLOR][COLOR=#007700]:        [/COLOR][COLOR=#0000BB]udata_shr

Retardo_100ms_d1    res 1
Retardo_100ms_d2    res 1

Retardo_code[/COLOR][COLOR=#007700]:       [/COLOR][COLOR=#0000BB]code

Retardo_100ms[/COLOR][COLOR=#007700]:
                                    ;[/COLOR][COLOR=#0000BB]99993 ciclos
                    movlw   0x1E
                    movwf   Retardo_100ms_d1
                    movlw   0x4F
                    movwf   Retardo_100ms_d2

Retardo_100ms_loop[/COLOR][COLOR=#007700]:
                    [/COLOR][COLOR=#0000BB]decfsz  Retardo_100ms_d1[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]f
                    [/COLOR][COLOR=#007700]goto    $+[/COLOR][COLOR=#0000BB]2
                    decfsz  Retardo_100ms_d2[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]f
                    [/COLOR][COLOR=#007700]goto    [/COLOR][COLOR=#0000BB]Retardo_100ms_loop

                                    [/COLOR][COLOR=#007700];[/COLOR][COLOR=#0000BB]3 ciclos
                    [/COLOR][COLOR=#007700]goto    $+[/COLOR][COLOR=#0000BB]1
                    nop

                                    [/COLOR][COLOR=#007700];[/COLOR][COLOR=#0000BB]4 ciclos [/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]incluyendo la llamada[/COLOR][COLOR=#007700])
                    return

; [/COLOR][COLOR=#0000BB]Generado por delay_pic[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000BB]pl [/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]Joaquín Ferrero[/COLOR][COLOR=#007700]. [/COLOR][COLOR=#0000BB]2014.07.22[/COLOR][COLOR=#007700])
; ./[/COLOR][COLOR=#0000BB]delay_pic[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000BB]pl [/COLOR][COLOR=#007700]-[/COLOR][COLOR=#0000BB]s Retardo_100ms 4Mhz 100ms
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]mar 22 jul 2014 19[/COLOR][COLOR=#007700]:[/COLOR][COLOR=#0000BB]22[/COLOR][COLOR=#007700]:[/COLOR][COLOR=#0000BB]23 CEST
[/COLOR][COLOR=#007700]; [/COLOR][COLOR=#0000BB]http[/COLOR][COLOR=#007700]:[/COLOR][COLOR=#FF8000]//perlenespanol.com/foro/generador-de-codigos-de-retardo-para-microcontroladores-pic-t8602.html
[/COLOR][COLOR=#007700]; ----------------------------------------------------------------------------------------------------

; ******************************************************************************


                    [/COLOR][COLOR=#0000BB]end  [/COLOR][/COLOR]


Antes de tocar algo.

¿Debo saber algo más?

Un saludo.

PD: Espero que no sea mucho de machacarte las neuronas por una adapación en asm.
 
Última edición:
#40
Porque otras personas que quieren montar el circuito no pueden debido a que su local de electrónica favorita no tienen el PIC16F88 y si el PIC16F630
Pero... si hoy en día todo el mundo compra la electrónica por Internet... Sale barato y te lo llevan a casa en menos de 48 horas...

junto con el decodificador de 7 segmentos 74LS48
¿Realmente lo necesitas? El PIC puede seguir entregando 7 salidas dedicadas para el dígito. Ese PIC tiene 12 E/S.

Además... fíjate que la patilla b siempre está a nivel alto, así que, te puedes ahorrar el conectarla al PIC :)
 
Última edición:
Arriba