Rebote de un pulsador en el ensamblaje utilizando la interrupción del temporizador1 - PIC16F628A [cerrado]

-1

Soy nuevo en la programación de ensamblajes y necesito desarrollar un código de rebote para usar en un botón pulsador, para eso debo usar la interrupción timer1.

El botón pulsador se utilizará para incrementar un contador que dará como resultado una pantalla de 7 seg. Ya lo tengo mostrando los números, usando un contador y una tabla, pero ahora estoy atascado en la interrupción, nunca hice nada de eso.

Debe haber un segundo botón que restablecerá el contador. Los botones pulsadores cambiarán de estado con "0" y solo deben contar un número mientras se presionan sin importar la duración del clic. Si alguien pudiera publicar un ejemplo estaría muy agradecido. Saludos

    
pregunta ERS

1 respuesta

2

Aquí hay algo de la ayuda prometida.

El PIC16F628A tiene dos vectores que necesita configurar. A menudo se hace algo como esto:

        ORG 000H
        GOTO MAIN

        ORG 004H
        GOTO ALLINTS

        ORG 010H
MAIN

Cuando el procesador se reinicie, se iniciará en MAIN. Pero si ocurre una interrupción (de cualquier fuente), entonces se derivará a ALLINTS. Los nombres pueden ser lo que quieras, sin embargo. Pero esos serán suficientes aquí.

Puede anular todos y cada uno de los conmutadores en PORTA, a la vez. (Consulte el código que he proporcionado para un procesador diferente aquí: ¿Diferencias entre interrupciones y muestreo para el botón de hardware?

Su código PRINCIPAL deberá inicializar el temporizador según mis preferencias de \ $ 8 \: \ textrm {ms} \ $. Asumiré que \ $ 4 \: \ textrm {MHz} \ $ es la velocidad del reloj operativo. Si configura una división por 8, su contador deberá comenzar en -1000 y restablecerse a eso, cada evento de interrupción. Por supuesto, deberá inicializar las variables y el registro TMR1 y los bits de configuración asociados en T1CON.

Algunas de las variables que estoy considerando podrían estar ubicadas en un CBLOCK, como este:

        CBLOCK
SWDEBPREV   
SWDEBCURR   
T1_SAVEW    
T1_SAVES    
T1_STPREV   
T1_STCURR   
T1_SWPREV   
T1_SWCURR   
        ENDC

Necesitarás una constante, como esta:

COUNTDOWN   EQU     -1000

El código PRINCIPAL (reemplace el ejemplo anterior con el siguiente) podría comenzar algo como esto:

        ORG     010H
MAIN        
        ; TODO: Configure PORTA as required. Assume all switches are on PORTA.

            CLRF    INTCON
            CLRF    SWDEBPREV
            CLRF    SWDEBCURR
            CLRF    T1_SWPREV
            CLRF    T1_SWCURR
            CLRF    T1_STPREV
            CLRF    T1_STCURR
            CLRF    PIR1
            BSF     STATUS, RP0
            CLRF    PIE1
            BSF     PIE1, TMR1IE
            BCF     STATUS, RP0
            MOVLW   34H
            MOVWF   T1CON
            MOVLW   LOW COUNTDOWN
            MOVWF   TMR1L
            MOVLW   LOW (COUNTDOWN >> 8)
            MOVWF   TMR1H
            BSF     INTCON, PEIE
            BSF     INTCON, GIE
            BSF     T1CON, TMR1ON
LOOP        
        ; TODO: Use SWDEBCURR and SWDEBPREV here.

            GOTO    LOOP        

Eso es antes de entrar en el LOOP principal que sondea las cosas.

Salte del bucle principal por un minuto y vayamos a la rutina de interrupción. He proporcionado un enlace anterior que proporciona la lógica básica de la máquina de estado que se puede aplicar para rebotar un interruptor. Pero ... resulta que esta máquina de estado se puede realizar simultáneamente en un puerto completo a la vez, tan fácilmente como se realiza en un pin de puerto. El procesador funciona en bytes de 8 bits, ¿por qué no aprovechar eso?

El código de interrupción puede parecerse al siguiente código. Pero tenga en cuenta que asumo (por ahora) que solo hay una una interrupción habilitada. Estoy haciendo esta suposición porque (1) no tengo información sobre otras interrupciones; y, (2) complicaría mucho las cosas.

ALLINTS     MOVWF   T1_SAVEW
            SWAPF   STATUS, W
            MOVWF   T1_SAVES

            BCF     T1CON, TMR1ON
            MOVLW   LOW COUNTDOWN
            MOVWF   TMR1L
            MOVLW   LOW (COUNTDOWN >> 8)
            MOVWF   TMR1H
            BSF     T1CON, TMR1ON

            MOVF    SWDEBCURR, W    ; Make the last debounced value
            MOVWF   SWDEBPREV       ;   the prior debounced value.
            MOVF    T1_STCURR, W    ; Make the last switch state value
            MOVWF   T1_STPREV       ;   the prior switch state value.
            MOVF    T1_SWCURR, W    ; Make the last raw port value
            MOVWF   T1_SWPREV       ;   the prior raw port value.
            MOVF    PORTA, W        ; Read the port and save it as
            MOVWF   T1_SWCURR       ;   the current raw port value.
            MOVWF   SWDEBCURR       ; Start as debounced value, too.
            XORWF   T1_SWPREV, W
            MOVWF   T1_STCURR
            IORWF   T1_STPREV, F
            COMF    W, W
            ANDWF   SWDEBCURR, F
            MOVF    T1_STPREV, W
            ANDWF   SWDEBPREV, W
            IORWF   SWDEBCURR, F    ; Generate final debounced value.

            MOVF    T1_SAVES, W
            SWAPF   STATUS, W
            MOVF    T1_SAVEW, W
            BCF     PIR1, TMR1IF
            RETFIE

He intentado evitar cualquier necesidad de cambiar de banco en el código anterior y eso simplifica el ahorro de estado, solo un poco. Ha pasado un tiempo (bueno, 10 años) desde que escribí el código PIC16. Así que por favor revísalo cuidadosamente para ver si hay errores. Creo que tengo la lógica interna básica correcta. Pero el ahorro y restauración del estado merece una mirada de cerca. (También tenga en cuenta que al reiniciar TMR1 sentí que tenía que deshabilitar el contador el tiempo suficiente para cargar el siguiente valor de la cuenta regresiva. Esto hará que el tiempo se "deslice" un poco; el tiempo entre las interrupciones no será exactamente \ $ 8 \: \ textrm {ms} \ $. Pero esto está bien solo para deshacer los interruptores. Por lo tanto, no tuve más problemas al respecto.)

El código PRINCIPAL ahora solo necesita observar los estados de devolución. Si desea buscar un valor de botón específico, puede leer SWDEBCURR y enmascararlo con la máscara apropiada que sea necesaria para extraer el pin específico y luego probar el valor del bit de rebote.

Si, en cambio, desea buscar un cambio en el botón de rebote, lea SWDEBCURR y XOR con SWDEBPREV. Aquellos bits que luego se configuran en 1 son casos en los que ha habido un botón de DEBICACIÓN o LIBERACIÓN de rebote.

La opción que quieras es tuya.

    
respondido por el jonk

Lea otras preguntas en las etiquetas