Soy completamente nuevo en el ensamblaje y debo desarrollar un contador usando PIC16F628A, un botón pulsador y una pantalla. Adicionalmente habrá un oscilador externo (555).
Hice algunos progresos en esto, pero creo que necesito ayuda de ustedes. Al principio hice un retraso basado en decrementos para poder ver los números en la pantalla.
Mi problema ahora es que una vez que presiono el botón, necesito que cuente solo un número, independientemente de cuánto tiempo lo mantenga presionado. Algo así como, si cambia de estado, incrementará 1. Creo que esto debe hacerse con interrupciones, supongo.
Ahora bien, ¿cuál es la mejor solución a mi problema? ¿Interrupción externa, por interrupción de estado? ¿Alguna otra cosa?
Dado que no puede usar un temporizador (recopilado de los comentarios que ha realizado), necesita una rutina de retraso adecuada para proporcionar un período de tiempo específico. me gusta el periodo de , por experiencia previa. Pero puede usar cualquier período que considere apropiado. Suponiendo que su procesador está utilizando el calibrado de fábrica tasa, el ciclo de instrucción será y tomará ciclos para formar un período.
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 como:
dónde y , 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 debería tomar exactamente ciclos y, en esto significa .
Tendrás que crear esas dos variables, y 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 algún lugar específico.
Ahora que tiene una rutina de retraso, puede continuar con el siguiente paso. Necesitas dos rutinas nuevas. Uno que retrasa repetidamente hasta que el botón se vuelve activo y otro que retrasa repetidamente hasta que el botón se vuelve inactivo. El antirrebote está incluido 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 número de puerto o pin, así que solo puse valores "ficticios" allí. Necesitas reemplazarlos, correctamente. Las dos rutinas anteriores asumen 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 estarlo, pero ¿y si lo está?), entonces el código restablecerá el contador y lo mostrará... pero esperará hasta que lo suelte. antes de continuar. Así que tienes que soltar el interruptor.
Luego, una vez que eso ha sucedido, el ciclo básico solo espera un estado activo de rebote del interruptor. Cuando ve eso, incrementa el contador inmediatamente (al presionar, no al soltar) pero luego espera a que se suelte el botón antes de continuar, nuevamente.
Eso es todo. Todavía necesita escribir el código apropiado para el contador y la pantalla. Pero eso transmite la idea al resto.
Necesitas "rebotar" tu interruptor. Esto se puede hacer en el hardware agregando un pequeño condensador a través de la entrada o en el software al verificar que el interruptor mantenga su estado durante el tiempo suficiente.
Ahora, el otro problema es que necesito agregar el valor de 1 una vez y solo una vez mientras presiono el botón. Imagine el botón presionado por 1 minuto y no debe agregar más que el incremento inicial de 1.
Ahora necesita un software "one-shot". Debe recordar si se presionó el botón la última vez que miró.
// Pseudo code
if(button) { // Button was pressed
if(!buttonMemory) { // Button was off last time we looked.
counter ++; // Increment the counter
buttonMemory = true; // Remember the button was pressed.
}
} else {
buttonMemory = false; // Cancel the memory.
}
Hay varios problemas. Parece por su vaga descripción que desea medir el tiempo que se presiona un botón. Tiene dos problemas, eliminar el rebote del botón y medir el tiempo que el botón bloqueado está presionado.
Haría ambas cosas en una interrupción periódica de 1 ms. Acostúmbrate a hacer eso. Un tic de reloj de 1 ms es útil para muchas cosas.
En este procesador en particular, el temporizador 2 con su registro de período incorporado es muy adecuado para esto. Configúrelo para que provoque una interrupción cada 1 ms (velocidad de 1 kHz).
En la rutina de interrupción, primero elimina el rebote del botón. Me gusta usar 50 ms como período de rebote. La mayoría de los botones rebotan durante unos 10 ms, pero he visto algunos que rebotan casi 50 ms. Además, ese es aproximadamente el tiempo máximo que los humanos no notan como un retraso, por lo que no hay daño a 50 ms para la experiencia del usuario.
Mantenga una bandera que sea el estado oficial de rebote del botón. Cuando el estado instantáneo del botón sea el mismo, restablezca el contador de rebotes a 50. Cuando los estados instantáneo y de rebotes del botón difieran, disminuya el contador. Cuando el contador llegue a 0, cambie el estado de rebote al estado actual del botón y restablezca el contador a 50.
Ahora que tiene el estado de rebote del botón, simplemente cuente cada vez que se presiona el botón y no haga nada cuando se suelta. En el caso especial de una transición de abajo a arriba, guarde el valor del contador y establezca una bandera para el código de primer plano que indica que hay disponible una nueva longitud medida. Limpia el contador.
Este contador deberá tener varios bytes de longitud. Un solo byte solo puede contar hasta 255, que es aproximadamente ¼ de segundo. Con dos bytes, el botón se puede mantener presionado durante un poco más de un minuto. Eso podría ser lo suficientemente bueno. Solo para estar seguro, solo debe incrementar el contador cuando aún no esté al máximo. De esa manera, una pulsación prolongada de un botón solo recorta el valor máximo representable.
broma
SRE
gbarry
SRE
usuario253751