No me funciona código en ensamblador de un contador

Buenos días amigos, les escribo porque no entiendo el por que no funciona este código para pic 16F877a, está hecho en ensamblador y se trata de un contador ascendente y descendente.
Se utilizan dos botones, uno conectado al puerto A en el pin 0 y otro en el puerto A en el pin 1.
Este código daría a conocer por donde va una cuenta en binario a través del puerto B.

Este es el código ensamblador.

Código:
List    p=16F877A    ;Tipo de procesador
        include    "P16F877A.INC"    ;Definiciones de registros internos


        org    0x00        ;Vector de Reset
        goto    Inicio
Inicio
dato equ 0x20
movlw 0x6
movwf dato
 clrf     PORTB        ;Borra los latch de salida
        bsf    STATUS,RP0    ;Selecciona banco 1
        movlw    b'00000110'
        movwf    ADCON1        ;Puerta A  digital
        clrf    TRISB        ;Puerta B se configura como salida
        movlw    b'00001111'        
        movwf    TRISA        ;Puerta A se configura como entrada
        bcf    STATUS,RP0    ;Selecciona banco 0
        movlw 0x0
        movwf PORTB

programa
btfsc PORTA,0
goto precontar
btfsc PORTA,1
goto predescontar
goto programa

precontar
btfss PORTA,0
goto contar
goto precontar

predescontar
btfss PORTA,0
goto descontar
goto predescontar

contar
movlw 0x02
addwf dato,1
movlw dato
movwf PORTB
goto programa

descontar
movlw 0x02
subwf dato,1
movlw dato
movwf PORTB
goto programa
end
 
Última edición por un moderador:
se trata de un contador ascendente y descendente.
Se utilizan dos botones, uno conectado al puerto A en el pin 0 y otro en el puerto A en el pin 1.
Este código daría a conocer por donde va una cuenta en binario a través del puerto B.
¿Y si haces algo más sencillo, así como esto?
Código:
    list        p=16f877a
    include        p16f877a.inc
    __config    _XT_OSC & _WDTE_OFF & _PWRTE_ON & _LVP_OFF
    errorlevel    -302

    cblock    0x20
    ret1,ret2,ret3            ; Variables para retardo
    endc

    org    0x00

Inicio
    bsf        STATUS,RP0        ; Ir al banco 1
    movlw    0x06
    movwf    ADCON1            ; Puertos A y E como digitales
    clrf    TRISB            ; Puerto B como salidas
    bcf        STATUS,RP0        ; Ir al banco 0
    clrf    PORTB            ; Puerto B en 0 al iniciar

sumar
    [B]btfsc    PORTA,1[/B]            ; Comprobar si RA1 es 0
    [B]goto    restar[/B]            ; No es 0, ir a rutina restar
    [B]incf    PORTB,f[/B]            ; RA1 es 0, incrementar los bits del puerto B
    [B]call    retardo.5[/B]        ; Retardo de 500Ms.
restar
   [B] btfsc    PORTA,0 [/B]           ; Comprobar si RA0 es 0
    [B]goto    sumar [/B]           ; No es 0, ir a rutina sumar
    [B]decf    PORTB,f [/B]           ; RA0 es 0, decrementar los bits del puerto B
    [B]call    retardo.5[/B]        ; retardo de 500Ms.
    [B]goto    sumar[/B]            ; Ir a rutina sumar para hacer un bucle

; Subrutina de retardo de 500Ms @ 4MHz.
retardo.5
    movlw    0x03
    movwf    ret1
    movlw    0x18
    movwf    ret2
    movlw    0x02
    movwf    ret3
retardo.5_0
    decfsz    ret1,f
    goto    $+2
    decfsz    ret2,f
    goto    $+2
    decfsz    ret3,f
    goto    retardo.5_0
    goto    $+1
    return

    end
Saludos.
 
A ver, como dice D@rkbytes, para contar y descontar hasta incrementos de 2 es más obvio poner uno o dos incf y decf antes que movwf esto movf lo otro.

Por otro lado si haces DATO EQU PORTB no necesitas guardar nada en dato, por lo que el código de incremento se reduce a dos instrucciones: movlw 0x02 y addwf PORTB.

Y por último, ya has visto que en la rutina de D@rkbytes tienes un retardo de 500ms. Este retardo tiene 2 objetivos. Por un lado evita los rebotes del pulsador, de manera que el micro descarta pulsaciones repetidas menores a 500ms, y por otro lado te da tiempo a ti a soltar el pulsador para que no siga contando solo. Si no pones ese retardo, a poco que mantengas el pulsador apretado contará a la velocidad del código del programa, es decir, una cuenta cada pocos microsegundos, por lo que obviamente el puerto tendrá cualquier cosa a su salida cuando dejes de apretar.

En tu caso has previsto que no cuente hasta que no se suelte el pulsador porque esperas un cambio de estado para sumar o restar, pero no has previsto los rebotes, por lo que pasará lo que te he dicho, que en lugar de contar de 2 en 2, te contará de 20 en 20 o depende de los rebotes que tengas en cada pulsador.
 
Última edición:
hola ignaciolin4

en el codigo vi:

precontar
btfss PORTA,0
goto contar
goto precontar


no deberia ser:

precontar
btfss PORTA,0
goto precontar
goto contar
 
Hola, muchas gracias por sus respuestas. He revisado y probado el codigo de D@rkbytes y no me funciona correctamente, al igual que mi codigo suma y resta, pero despues de incrementar un valor, no incrementa mas, y despues de de restar un valor no resta, se queda como estancado. No entiendo porque sucede esto. Mi codigo tiene el mismo error, suma un numero, pero despues no suma mas, al igual que la resta. JDC Depende de la forma en que coloques los pulsadores, yo los tengo puesto de la siguiente manera, una pata del pulsado va a 5v, la otra pata va conectada al pic, y al mismo tiempo esta conectada a una resistencia y esta a su vez esta conectada a tierra. Por eso tengo el anti rebote programado de esta forma. El codigo de D@rkbytes tiene los pulsadores conectados de forma contraria, y en este caso tu forma de la programacion de anti rebotes si estaria correcta. Por favor, ayudenme en esto, por no entiendo el porque no aumenta mas de una vez, o porque no disminuye mas de una vez. Lo probe en el simulador de ISIS Proteus 8.
 
El código que puse si funciona, lo único que debiste haber hecho es cambiar BTFSC por BTFSS para invertir la comprobación.
También pudiste haber cambiado las resistencias, en vez de ser Pull-Up, las pones Pull-Down.

Aquí lo adjunto con ese único cambio, incluyendo la simulación.

Suerte.
 

Adjuntos

  • 16F877A Contador Binario.rar
    44.8 KB · Visitas: 191
aaaah ya entiendo porque a mi no me funcionaba. Creo que fue por le coloque, en la simulación, un bar led, en vez de colocar led simple con sus resistencias. Creo que es fue el error ya funciona perfecto. Muchas gracias a todos, me han ayudado un montón. De verdad muchas gracias.



Una pregunta D@rkbytes que version de MPLAB tienes tu? porque cuando voy a compilar tu mismo proyecto en mi mplab me da error y cuando elimino el error no me funciona correctamente el programa para el pic. Pero el que tu me enviaste que ya esta en formato *.hex si funciona perfecto. no entiendo porque mi MPLAB se comporta de esta menera. De verdad gracias por todo.
 
Última edición:
tienes el error de incrementar el dato en 2 sin ponerlo a cero y no lo mueves al registro W
contar
movlw 0x02
addwf dato,1
movf dato,w
movwf PORTB
goto programa
.............
aqui esta corregido pero sigue el conteo de dos en dos
 
Este es el error que me sale Error[113] C:\USERS\ADMIN\DOWNLOADS\16F877A CONTADOR BINARIO\16F877A CONTADOR BINARIO\CONTADOR.ASM 3 : Symbol not previously defined (_WDTE_OFF)

Claro, con razon, yo lo estoy copilando en la version 8.3 Me imagino que es por eso.
 
Este es el error que me sale Error[113] Symbol not previously defined (_WDTE_OFF)

Claro, con razón, yo lo estoy copilando en la versión 8.3 Me imagino que es por eso.
Si, conforme van avanzando las versiones de MPLAB se han ido modificando los nombres para los fuses.
Si no quieres descargar y actualizar la versión de MPLAB que tienes, utiliza _WDT_OFF en vez de _WDTE_OFF

Con ese cambio, en tu versión de MPLAB lo debes poder compilar sin problemas.
 
Atrás
Arriba