Modificar este código a algo más complejo

#1
Hola:

Siendo este código en asm para PIC16F84A, ya lo pasaré a PIC16F88.

Código:
; Implementar una tabla de la verdad mediante el manejo de tablas grabadas en ROM.
; Por ejemplo, la tabla será de 3 entradas y 6 salidas tal como la siguiente:
; 
;         C  B  A  | S5  S4  S3  S2  S1  S0
;         -----------|---------------------------
;         0   0   0   |   0    0    1    0    1    0    ; (Configuración 0).
;         0   0   1   |   0    0    1    0    0    1    ; (Configuración 1).
;         0   1   0   |   1    0    0    0    1    1    ; (Configuración 2).
;         0   1   1   |   0    0    1    1    1    1    ; (Configuración 3).
;         1   0   0   |   1    0    0    0    0    0    ; (Configuración 4).
;         1   0   1   |   0    0    0    1    1    1    ; (Configuración 5).
;         1   1   0   |   0    1    0    1    1    1    ; (Configuración 6).
;         1   1   1   |   1    1    1    1    1    1    ; (Configuración 7).
;
; Las entradas C, B, A se conectarán a las líneas del puerto A: RA2 (C), RA1 (B) y RA0 (A).
; Las salidas se obtienen en el puerto B:
; RB5 (S5), RB4 (S4), RB3 (S3), RB2 (S2), RB1 (S1) y RB0 (S0).
;
; ZONA DE DATOS **********************************************************************

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

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

    ORG     0                    ; El programa comienza en la dirección 0.
Inicio
    bsf        STATUS,RP0            ; Acceso al Banco 1.
    clrf    TRISB                ; Las líneas del Puerto B se configuran como salida.
    movlw    b'00011111'            ; Las 5 líneas del Puerto A se configuran como entrada.
    movwf    TRISA
    bcf        STATUS,RP0            ; Acceso al Banco 0.
Principal
    movf    PORTA,W                ; Lee el valor de las variables de entrada.
    andlw    b'00000111'            ; Se queda con los tres bits de entrada.
    addwf    PCL,F                ; Salta a la configuración adecuada.
Tabla
    goto    Configuracion0
    goto    Configuracion1
    goto    Configuracion2
    goto    Configuracion3
    goto    Configuracion4
    goto    Configuracion5
    goto    Configuracion6
    goto    Configuracion7
Configuracion0
    movlw     b'00001010'            ; (Configuración 0).
    goto    ActivaSalida
Configuracion1
    movlw     b'00001001'            ; (Configuración 1).
    goto    ActivaSalida
Configuracion2
    movlw     b'00100011'            ; (Configuración 2).
    goto    ActivaSalida
Configuracion3
    movlw     b'00001111'            ; (Configuración 3).
    goto    ActivaSalida
Configuracion4
    movlw     b'00100000'            ; (Configuración 4).
    goto    ActivaSalida
Configuracion5
    movlw     b'00000111'            ; (Configuración 5).
    goto    ActivaSalida
Configuracion6
    movlw     b'00010111'            ; (Configuración 6).
    goto    ActivaSalida
Configuracion7
    movlw     b'00111111'            ; (Configuración 7).
ActivaSalida
    movwf    PORTB                ; Visualiza por el puerto de salida.
    goto     Principal

    END
Partiendo del código de arriba, quiero hacer una tabla de la verdad para un display de 7 segmentos y la otra tabla es para configuración a otra cosa. En dicho display debe contar del 1 al 4.

La idea consiste con un pulsador, incrementar las dos tablas de la verdad.

¿Esto es posible?

Si no entiendes, lo explico de otra manera.

Un saludo.
 
#2
Usá vectores inicializados con el código en 7 segmentos, en assembler sería usar posiciones de memorias continuas, ejemplo:

Dir Base: 0b01111110 (el 0 en el display)
Dir Base + 1: 0b00110000 (el 1 en el display)
....
Dir Base + 9: 0b01111011 (el 9 en el display)

Entonces desde tú código, solo tenes que leer la posición de memoria acorde al número que necesitas leer:

Leo "Dir Base + 1" => obtengo el 7 segmentos del número 1.

Más detalles, acá tenés una explicación, pero en C:

https://www.forosdeelectronica.com/f24/funciones-varias-pic-c-111204/
 
#3
Lo mejor es usar una tabla de salto, muy típica de estos procesadores:
PHP:
;
; Implementar una tabla de la verdad mediante el manejo de tablas grabadas en ROM.
;
; Por ejemplo, la tabla será de 3 entradas y 6 salidas tal como la siguiente:
;
;   C   B   A  |   S5   S4   S3   S2   S1   S0
;   -----------|------------------------------
;   0   0   0  |   0    0    1    0    1    0    ; Configuración 0
;   0   0   1  |   0    0    1    0    0    1    ; Configuración 1
;   0   1   0  |   1    0    0    0    1    1    ; Configuración 2
;   0   1   1  |   0    0    1    1    1    1    ; Configuración 3
;   1   0   0  |   1    0    0    0    0    0    ; Configuración 4
;   1   0   1  |   0    0    0    1    1    1    ; Configuración 5
;   1   1   0  |   0    1    0    1    1    1    ; Configuración 6
;   1   1   1  |   1    1    1    1    1    1    ; Configuración 7
;
; Las entradas C, B, A se conectarán a las líneas del puerto A:
;   RA2 (C),
;   RA1 (B), y
;   RA0 (A).
;
; Las salidas se obtienen en el puerto B:
;   RB5 (S5), RB4 (S4), RB3 (S3), RB2 (S2), RB1 (S1) y RB0 (S0).
;

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

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

                processor   16F84A          ; 1 Mhz
                radix       dec
                errorlevel  -302            ; Turn off banking message

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

                include p16f84a.inc

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

                __CONFIG _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC


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

                ORG     0

Inicio:
                banksel TRISB           ; bank 1
                clrf    TRISB           ; puerto B como salida

                movlw   b'00011111'     ; puerto A como entrada
                movwf   TRISA

                banksel PORTA           ; bank 0

Principal:
                movf    PORTA, w        ; leer puerto
                andlw   b'00000111'     ; nos quedamos sólo con las interesantes

                call    a_digito        ; transformación a dígito

                movwf   PORTB           ; visualiza
                goto    Principal

; ******************************************************************************
;; a_digito
;
; Conversión de un valor almacenado en w [0-7] a un valor de tabla.
;

a_digito:       addwf   PCL, f          ; salta al valor indexado por w

                retlw   b'00001010'     ; Configuración 0
                retlw   b'00001001'     ; Configuración 1
                retlw   b'00100011'     ; Configuración 2
                retlw   b'00001111'     ; Configuración 3
                retlw   b'00100000'     ; Configuración 4
                retlw   b'00000111'     ; Configuración 5
                retlw   b'00010111'     ; Configuración 6
                retlw   b'00111111'     ; Configuración 7

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

                END
 
Última edición:
#4
Buenas:

Con vuestras ideas he sacado otras ideas. Ahora estoy algo más cerca de lo que quiero. Les recuerdo que quiero un display de 7 segmentos, se mostrará los números 1,2,3 y 4. Usará solo un pulsador en el RA4. Si estás en el número 4, se pondrá el número 1 otra vez.

En la otra tabla de la verdad, he usado las instrucciones bcf y bsf para tenerlo más fácil. Son salidas de datos que de momento he puesto Led como muestra en el dibujo de abajo.

La parte que no me funciona es la del pulsador y necesito ayuda, es decir, que cada pulso que haga, cuente en el display un número tal como dije arriba. Ahora si que estoy perdido.

PIC.png

Tabla-de-la-verdad.png

Código:
; Implementar una tabla de la verdad mediante el manejo de tablas grabadas en ROM.
; Por ejemplo, la tabla será de 1 pulsador y 8 salidas tal como la siguiente
; para el display de 7 segmentos y otras 4 salidas para datos.
; 
;       Pulsador RA4  |  RB7  RB6  RB5  RB4  RB3  RB2  RB1  RB0
;      ---------------|----------------------------------------
;               0   |   0    0    0    0    0    0    1    1    ; (Configuración 0).
;               1   |   0    0    1    0    0    1    0    0    ; (Configuración 1).
;               2   |   0    0    0    0    1    1    0    0    ; (Configuración 2).
;               3   |   0    0    1    1    1    1    0    0    ; (Configuración 3).

;
; La otra tabla para datos que usan los puertos A0, 1, 2 y 3.
; Hex    Dec    Datos    OE1    OE2    A21    AUX
;3    0    1    0    1    0    0
;5B    1    2    1    0    1    0
;4F    2    3    0    1    1    0
;66    3    4    1    0    0    1
; 
;
; ZONA DE DATOS **********************************************************************

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

#DEFINE    OE1    PORTA,0
#DEFINE    OE2    PORTA,1
#DEFINE    A21    PORTA,2
#DEFINE    AUX    PORTA,3
#DEFINE    Pulsador    PORTA,4

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

    ORG     0        ; El programa comienza en la dirección 0.
Inicio
    bsf    STATUS,RP0    ; Acceso al Banco 1.
    clrf    TRISB     ; Las líneas del Puerto B se configuran como salida.
    bcf    OE1    ; PORTA,0 o OE1 como salida.
    bcf    OE2    ; PORTA,1 o OE2 como salida.
    bcf    A21    ; PORTA,2 o A21 como salida.
    bcf    AUX    ; PORTA,3 o AUX como salida.
    bsf    Pulsador    ; PORTA,4 o Pulsador como entrada.
    bcf    STATUS,RP0      ; Acceso al Banco 0.
Principal
    movf    PORTA,W         ; Lee el valor de las variables de entrada.
    andlw    b'00000111'     ; Se queda con los tres bits de entrada.
    addwf    PCL,F           ; Salta a la configuración adecuada.
Tabla
    goto    Configuracion0
    goto        Configuracion1
    goto        Configuracion2
    goto        Configuracion3
Configuracion0
    bcf    OE1
    bsf    OE2
    bcf    A21
    bcf    AUX
    movlw         b'00000011'            ; (Configuración 0).
    goto        ActivaSalida
Configuracion1
    bsf    OE1
    bcf    OE2
    bsf    A21
    bcf    AUX
    movlw         b'01011011'            ; (Configuración 1).
    goto        ActivaSalida
Configuracion2
    bcf    OE1
    bsf    OE2
    bsf    A21
    bcf    AUX
    movlw         b'01001111'            ; (Configuración 2).
    goto        ActivaSalida
Configuracion3
    bsf    OE1
    bcf    OE2
    bcf    A21
    bsf    AUX
    movlw         b'01100110'            ; (Configuración 3).
ActivaSalida
    movwf        PORTB                ; Visualiza por el puerto de salida.
    goto         Principal

    END
El que quiera el esquem ahecho con Proteus 7.10, se lo paso y hacen pruebas. Incluido asm y hex.

Un cordial saludo.
 
#5
Debes hacer un bucle que quede leyendo RA4.

Si el valor es igual a 1, es que el pulsador no está activado, por lo que vuelve a repetir la lectura.

Si el valor es igual a 0, es que está pulsado.

Entonces, iniciamos un nuevo bucle, en donde primero esperamos una cantidad de tiempo (por ejemplo, 100 ms) y a continuación miramos el estado de RA4. Si el pulsador sigue pulsado, repetimos el bucle, y salimos si ya no lo está.

Y luego sigue el resto del programa.

Me parece que el uso de las instrucciones bsf y bcf... sí, son sencillas, pero alargan un poco, el programa. El uso de tablas retlw es lo propio, cuando queremos cambiar unos valores por otros.
 
Última edición:
#6
Hola de nuevo:

Hice el código desce cero, me funciona solo el Display de 7 seg. ya que me he metido ahí. Ahora me toca la otra tabla de la verdad, el de los datos.

Les vuelvo a subir la tabla de la verdad modificado algunos valores ya que la anterior tenía errores de configuración, ahora todo funciona bien del 1 al 4 y vuelve a contar de nuevo.

Ver el archivo adjunto 115023

Nuevo código más sencillo.
Código:
; Cada vez que presione el pulsador conectado al pin RA4 incrementa un contador visualizado
; en el display.
;
; ZONA DE DATOS **********************************************************************

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

    CBLOCK  0x0C
    Contador                        ; El contador a visualizar.
    ENDC

#DEFINE    OE1    PORTA,0
#DEFINE    OE2    PORTA,1
#DEFINE    A21    PORTA,2
#DEFINE    AUX    PORTA,3    
#DEFINE     Pulsador    PORTA,4            ; Pulsador conectado a RA4.
#DEFINE     Display    PORTB            ; El display está conectado al Puerto B.

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

    ORG    0                            ; El programa comienza en la dirección 0.
Inicio
      bsf    STATUS,RP0            ; Acceso al Banco 1.
    clrf    Display            ; Estas líneas configuradas como salidas.
    bcf    OE1
    bcf    OE2
    bcf    A21
    bcf    AUX
    bsf    Pulsador            ; Línea del pulsador configurada como entrada.
    bcf    STATUS,RP0            ; Acceso al Banco 0.
    call    InicializaContador        ; Inicializa el Contador y lo visualiza.
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    IncrementaVisualiza        ; Incrementa el contador y lo visualiza.
EsperaDejePulsar
    btfss    Pulsador            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar        ; No. Espera que deje de pulsar.
Fin    goto    Principal

; Subrutina "IncrementaVisualiza" ---------------------------------------------------------

IncrementaVisualiza
    incf    Contador,F            ; Incrementa el contador y comprueba si ha
    movlw     d'4'            ; llegado a su valor máximo mediante una
    subwf    Contador,W            ; resta. (W)=(Contador)-4.
    btfsc    STATUS,C            ; ¿C=0?, ¿(W) negativo?, ¿(Contador)<4?
InicializaContador
    clrf    Contador            ; No, era igual o mayor. Por tanto, resetea.
Visualiza
    movf    Contador,W
;    call    Numero_a_7Segmentos        ; Lo pasa a siete segmento para poder ser
    call    Tabla
    movwf    Display            ; visualizado en el display.
    return
Tabla
    addwf    PCL,F
    DT    06h, 5Bh, 4Fh, 66h        ; Números 1, 2, 3 y 4.


    INCLUDE <RETARDOS.INC>            ; Subrutinas de retardo.
    END                ; Fin del programa.
Ya que el código justo arriba funciona de maravilla, solo el display de 7 segmento del 1 al 4 y si sigues pulsando, vuelve al 1, como debe ser.

Falta la tabla de la verdad de datos de color verde como indica la imagen de arriba.

El problema es.

¿Cómo lo implemento como salidas y acorde al Display?

Saludo.
 
Última edición:
#7
Se pueden tener tantas tablas como quieras.

Esta es mi versión de tu programa. Por favor, fíjate en cómo hago para tener más de una tabla, y verás la cantidad de código que se puede ahorrar.
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.
;
; (Contador)  |RB 76543210 |RA 76543210
; ------------|------------------------
;       1     |   00000110 |   00000010
;       2     |   01011011 |   00000101
;       3     |   01001111 |   00000110
;       4     |   01100110 |   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

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

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

                    include p16f84a.inc

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

                    __CONFIG _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC


;*******************************************************************************
; 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 TRISA           ; bank 1

                    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 PORTA           ; bank 0, siempre
                    goto    Bucle

; Bucle principal
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
Bucle:
                    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     ; Si el contador valía 4, ahora vale 0
                    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

; 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
 
Última edición:
#8
Se pueden tener tantas tablas como quieras.

Esta es mi versión de tu programa. Por favor, fíjate en cómo hago para tener más de una tabla, y verás la cantidad de código que se puede ahorrar.
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.
;
; (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

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

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

                    include p16f84a.inc

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

                    __CONFIG _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC


;*******************************************************************************
; 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 TRISA           ; bank 1

                    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

; Bucle principal
                    banksel PORTA           ; bank 0, siempre
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
                    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:
                    incf    contador
                    decf    contador,w      ; leemos el contador, y le restamos 1

                    andlw   0x03            ; nos quedamos con los bits más bajos
                    btfss   STATUS, Z       ; ¿es cero?
                    return                  ; aún no, salimos

                    movlw   1               ; sí es cero: hemos pasado de 4
                    movwf   contador        ; lo pasamos a 1
                    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
; ----------------------------------------------------------------------------------------------------

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

                END
Buenísimo, me funciona a la primera. No sabía que se puediera hacer tantas tablas como quieras.

Hay un problema. Nada más encenderlo el simulador, me aparece un 7. Luego si pulso pulso el pulsador, nohay ningún problema. Solo al volver a encenderlo.

picd.png

Cuando al encender aparece un 7, al pulsar aparece un 1 hasta el 4, luego nada de fallos, solo al encender o resetear el PIC.

Voy analizar como hiciste las mezclas de tablas para aprenderlo.

Muchísimas gracias campeón.

Edito.

Para calcular retardos.
http://www.golovchenko.org/cgi-bin/delay

Saludo.
 
Última edición:
#9
Sin desmerecer tu código Joaquin, yo el incremento del contador lo haría de otra forma más corta...

PHP:
incrementa_contador:
                bcf    contador, 2   ; Si el contador valia 4, ahora vale 0
                incf    contador     ; Incrementa el contador
                return                 ; Hasta luego lucas!!
Meta, prueba a ver con alguna ligera modificación a ver si te va bien?

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.
;
; (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

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

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

                    include p16f84a.inc

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

                    __CONFIG _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC


;*******************************************************************************
; 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 TRISA           ; bank 1

                    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

; Bucle principal
                    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
                    call    incrementa_contador
Inicializado:
                    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

; 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
 
#10
Hola:

Se muestra un 0 en el Display y se queda ahí, el pulsador no hace caso. En resumen, no funciona. Se agradece resumir códigos.

Cuando esto funcione de maravilla. Quiero pasarlo al PIC16F88 real, ya que es el PIC que tengo ahora mismo. Les mostraré hasta un vídeo.

Gracias por sus tiempo.
 
Última edición:
#11
Cambia la etiqueta de inicializacion y ponla una instruccion antes, de esa forma al encender debe aparecer un 1. Si no es asi algo falla en la rutina de incremento. De todas formas es muy raro que falle solo he hexho un goto para una primera impresion en display y sustituir el incremento por las dos instrucciones. Es posible que se haya vuelto loca la tabla de porta al estar el.contador a cero.
 
#13
En un rato te contesto con el codigo. Estoy desde el telefono movil.

OK mira a ver si asi 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. 
; 
; (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 

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

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

                    include p16f84a.inc 

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

                    __CONFIG _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC 


;******************************************************************************* 
; 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 TRISA           ; bank 1 

                    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 

; Bucle principal 
                    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 

; 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
 
Última edición:
#15
Hola de nuevo.

Usando el MPLAb X 2.15 ahora mismo, antes usaba el MPLAB v8.92 (El fabricante ya no actualiza desde hace tiempo).

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

; 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

; 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
Lo he adaptado al PIC16F88 y me funciona con el oscilador externo. Quiero usar el oscilador interno a 4 MHz si es posible. Así me libro de componentes externos.

Sin-título-1.png

PD: Por cierto. No sabía que has hecho tu propio generador de retardos, es muy de agradecer. Si lo deseas, lo puedo poner como utilidad en la sección Utilidad de mi Blog.
 
Última edición:
#16
palurdo: gracias por encontrar una mejor solución para el incremento. Es cierto que había escrito demasiadas instrucciones para algo tan simple.

Meta: le hice ingeniería inversa al generador de retardos de Goglovchenko, porque había algunos comportamientos extraños con algunas combinaciones y, sobre todo, porque no querían compartir su código :) Aunque en su página dan muchas pistas, no estaba disponible. Así que, aprovechando que estaba aprendiendo a programar los temporizadores, de forma transversal salió el tema de los retardos por medio de bucles enlazados. Y de ahí luego la idea de crear un programa que reuniera el conocimiento aprendido, teniendo además la ventaja de que se podía personalizar la salida de forma más sencilla, editando unas pocas líneas del código. Y el resultado, en algunos casos muy puntuales, es mejor que el de Golovchenko :)

Aún no he terminado con él, ya que mis planes son las de crear una biblioteca Perl con él, y publicarlo en el CPAN, para que otras personas lo puedan usar de forma aún más sencilla.
 
#17
Buenas:



A pesar de asegurarme una y otra vez los Led del display rojo cátodo común con el PIC. Da resultados no esperado. En cuanto a los 4 Led azules, funciona muy bien.

¿Qué puede ser?

El código es este y juraría que la tabla de la verdad está 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

; 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

; 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
Espero que el oscilador interno a 4 Mhz esté bien puestos del PIC16F88.

Saludo.

PD: Es de agradece recortar código. En cuanto a los retardos, buen trabajo.
 
#18
El número de segmentos que se encienden son correctos, y además son consistentes entre sí (siguen la secuencia 1-4), pero... las conexiones están mal.

En el caso del '1', se deben encender RB0 y RB1, correspondientes a los segmentos 'b' y 'c', pero en realidad se están iluminando el 'c' y el 'd'. Así que... o el 'b' está cambiado o los dos están mal.

Por otra parte, me he dado cuenta de que la secuencia de bits de PORTB que hay en el comentario inicial en el programa, no es correcto, no sirve para el 7 segmentos. No afecta al código (es un comentario) pero queda feo. Y el foro ya no me deja cambiarlo :(
 
Última edición:
#19
Si no te deja cambiarlo, puedes poner el nuevo código aquí.

A parte de ello, parece que se puede mejorar o reducir a la hora de hacer varias tablas.
Por ejemplo.

Código:
[LIST=1]
[*]IncrementaVisualiza
[*]    incf    Contador[COLOR=#339933],[/COLOR]F            [COLOR=#666666][I]; Incrementa el contador y comprueba si ha[/I][/COLOR]
[*]    movlw     d[COLOR=#7f007f]'4'[/COLOR]            [COLOR=#666666][I]; llegado a su valor máximo mediante una[/I][/COLOR]
[*]    subwf    Contador[COLOR=#339933],[/COLOR]W            [COLOR=#666666][I]; resta. (W)=(Contador)-4.[/I][/COLOR]
[*]    btfsc    STATUS[COLOR=#339933],[/COLOR][B]C[/B]            [COLOR=#666666][I]; ¿C=0?, ¿(W) negativo?, ¿(Contador)<4?[/I][/COLOR]
[*]InicializaContador
[*]    clrf    Contador            [COLOR=#666666][I]; No, era igual o mayor. Por tanto, resetea.[/I][/COLOR]
[*]Visualiza
[*]    movf    Contador[COLOR=#339933],[/COLOR]W
[*][COLOR=#666666][I];    call    Numero_a_7Segmentos        ; Lo pasa a siete segmento para poder ser[/I][/COLOR]
[*]    [COLOR=#00007f][B]call[/B][/COLOR]    Tabla
[*]    movwf    Display            [COLOR=#666666][I]; visualizado en el display.[/I][/COLOR]
[*]    movf    Contador[COLOR=#339933],[/COLOR]W
[*]    [COLOR=#00007f][B]call[/B][/COLOR]    Tabla2
[*]    movwf    PORTA
[*]    return
[*]Tabla
[*]    addwf    PCL[COLOR=#339933],[/COLOR]F
[*]    [B]DT[/B]    [COLOR=#0000ff]06h[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#0000ff]5Bh[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#0000ff]4Fh[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#0000ff]66h[/COLOR]        [COLOR=#666666][I]; Números 1, 2, 3 y 4.[/I][/COLOR]
[*]Tabla2
[*]    addwf    PCL[COLOR=#339933],[/COLOR]F
[*]    [B]DT[/B]    [COLOR=#0000ff]02h[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#0000ff]05h[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#0000ff]06h[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#0000ff]0Ah[/COLOR]
[/LIST]
En cuanto a las conexiones, lo estoy revisando palmo a palmo.

Gracias.

Edito:

Efectivamente. Son las conexiones. Ahora funciona muy bien.
 

Adjuntos

Última edición:
#20
Al final, sí que me dejó. He reeditado el mensaje #7, arreglando el comentario inicial y agregando los cambios de palurdo.

En cuanto a usar dt... me parece que justo este problema es un buen ejemplo en que los dt no son lo recomendable. Es cierto que generan el mismo código que los retlw (generan el mismo código binario), pero en un asunto en que tenemos que lidiar con líneas de bits, prefiero verlos (los bits); por eso habrás visto en mi código líneas así:

|76543210|

que ayudan en la des/activación de bits individuales.

Yo prefiero no andar calculando el valor decimal o hexadecimal de los bytes y ponerlos en los dt... el mantenimiento posterior es mucho más difícil.

Los dt vienen bien, por ejemplo, para poner tablas de multiplicadores/divisores:

dt 100,10,1
 
Última edición:
Arriba