Dado que no puede usar un temporizador (recopilado de los comentarios que ha realizado), necesita una rutina de demora adecuada para proporcionar un período de tiempo específico. Me gusta el período de \ $ 8 \: \ textrm {ms} \ $, de la experiencia anterior. Pero puedes usar cualquier período que consideres apropiado. Suponiendo que su procesador utiliza la tasa \ $ 4 \: \ textrm {MHz} \ $ calibrada de fábrica, el ciclo de instrucción será \ $ 1 \: \ mu \ textrm {s} \ $ y tomará \ $ 8,000 \ $ ciclos para inventa un \ $ 8 \: \ textrm {ms} \ $ period.
El código de retardo probablemente debería convertirse en una subrutina, para evitar tener que replicarlo una y otra vez.
DELAY8MS MOVLW 0x3E
MOVWF DLO
MOVLW 0x07
MOVWF DHI
DECFSZ DLO, F
GOTO $+2
DECFSZ DHI, F
GOTO $-3
NOP
GOTO $+1
RETURN
El tiempo total ocupado por la rutina anterior se puede calcular de la siguiente manera:
$$ t = 5 \ cdot \ left [D_ {LO} + 2 + 256 \ cdot \ left (D_ {HI} -1 \ right) \ right] $$
donde \ $ 1 \ le D_ {LO} \ le 256 \ $ y \ $ 1 \ le D_ {HI} \ le 256 \ $, con 0 interpretado como 256. Las instrucciones CALL y RETURN toman 2 ciclos cada una y El código anterior tiene todo eso en cuenta. Llamarlo debe tomar exactamente \ $ 8,000 \ $ ciclos y, en \ $ 4 \: \ textrm {MHz} \ $ esto significa \ $ 8 \: \ textrm {ms} \ $.
Tendrá que crear esas dos variables, \ $ D_ {LO} \ $ y \ $ D_ {HI} \ $ en algún lugar. Eso se puede hacer así, creo:
CBLOCK
DLO
DHI
ENDC
Hay, por supuesto, otras formas. Y puede agregar una dirección absoluta a la línea CBLOCK si desea colocar el bloque en un lugar específico.
Ahora que tiene una rutina de demora, puede continuar con el siguiente paso. Necesitas dos nuevas rutinas. Una que se retrasa repetidamente hasta que el botón se active y otra que se retrasa hasta que el botón se desactiva. El anuncio se incluye aquí:
ACTIVE CALL DELAY8MS
BTFSC PORTx, PINy
GOTO ACTIVE
CALL DELAY8MS
BTFSC PORTx, PINy
GOTO ACTIVE
RETURN
INACTIVE CALL DELAY8MS
BTFSS PORTx, PINy
GOTO INACTIVE
CALL DELAY8MS
BTFSS PORTx, PINy
GOTO INACTIVE
RETURN
No sé su puerto o número de pin, así que simplemente puse los valores "ficticios" allí. Necesitas reemplazarlos, correctamente. Las dos rutinas anteriores suponen que 0 está activo y 1 está inactivo.
Ahora puedes escribir tu código principal:
MAIN ; <code to reset your counter value>
GOTO LOOP_NXT
LOOP CALL ACTIVE
; <code to increment your counter value>
LOOP_NXT ; <code to display your counter value>
CALL INACTIVE
GOTO LOOP
El código anterior restablece el valor de su contador a lo que quiera comenzar y luego salta al bucle donde muestra el valor y espera a que el botón se vuelva inactivo. El efecto aquí es que si inicia su código con el botón presionado (no debería ser, pero ¿qué pasa si lo es?), Entonces el código aún reiniciará el contador y lo mostrará ... pero esperará hasta que suelte antes de continuar. Así que tienes que dejar el interruptor.
Luego, una vez que esto ha sucedido, el bucle básico solo espera un estado activo de rebote del conmutador. Cuando ve eso, incrementa el contador inmediatamente (en la prensa, no en el lanzamiento) pero luego espera a que se suelte el botón antes de continuar, nuevamente.
Eso es todo. Aún necesita escribir el código apropiado para el contador y la pantalla. Pero eso da a entender la idea del resto.