Autor Tema: No logro hacer que funcionen las interrupciones por RB0  (Leído 3799 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Rayloool

  • PIC10
  • *
  • Mensajes: 5
No logro hacer que funcionen las interrupciones por RB0
« en: 04 de Marzo de 2018, 19:32:33 »
No logro hacer que funcionen las interrupciones del puerto b, soy principiante en programación de pic's y llevo 2 dias intentando hacer que funcione una interrupción por RB0 eh estado investigando y por mas que leia y leia en foros y revisaba videos, no soy capaz de resolverlo por ello me eh unido a esta comunidad y preguntar directamente si alguien podria ayudarme a resolverlo :C
Espero alguien pueda ayudarme me esta volviendo loco

Estoy haciendo un programa el cual un led parpadea a medio segundo de manera constante haciendo uso del desbordamiento de TMR0 aun que sin activar TOIE para que no salte a la interrupción "no se si eso afecte" y al crear una interrupción por RB0, mientras mantengo pulsado RB0 no pasa nada y no es si no hasta cuando dejo de pulsar que parpadea 3 veces mas a medio segundo igualmente y luego se apaga hasta presionar RB1 que regresa a encender y apagar a medio segundo esperando la interrupcion, todo esto fue puesto por mi para el aprendizaje de las interrupciones help me :(
no se como insertan el codigo asi que solo lo copie y lo pegue
   list      p=16f886   
   #include   <p16f886.inc>   

   __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
   __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

   ORG     0x000   
   GOTO   INICIO
   ORG      0X004
   GOTO   ATIENDE
   ORG      0X005
CICLO
   BTFSC   PORTB,0
   GOTO   CICLO
   GOTO   ATIENDE
   RETFIE
INICIO
   BSF    INTCON,GIE   
   BSF    INTCON,INTE   
   BSF      STATUS,RP0
   MOVLW   0X35
   MOVWF   OSCCON
   MOVLW   0X57
   MOVWF   OPTION_REG
   BCF      TRISC,0
   BSF      STATUS,RP1
   CLRF   ANSELH
   CLRF   ANSEL
   CLRF   STATUS
NADA
   CALL   PROGRAMA
   GOTO   NADA

PROGRAMA
   BSF      PORTC,0
   CALL   TMRO
   BCF      PORTC,0
   CALL   TMRO
   RETURN

TMRO
   MOVLW   .12
   MOVWF   TMR0
   BCF      INTCON,T0IF
DESBORDE
   BTFSS   INTCON,T0IF
   GOTO   DESBORDE
   RETURN
ATIENDE
   BTFSS   PORTB,1
   BCF      INTCON,INTF
   BTFSS   PORTB,1
   CALL   PROGRAMA
   BTFSS   PORTB,1
   CALL   PROGRAMA
   BTFSS   PORTB,1
   CALL   PROGRAMA
   BTFSS   PORTB,1
AQUI
   BCF      PORTC,0
   BTFSS   PORTB,1
   GOTO   AQUI
   BCF      INTCON,INTF
   RETFIE

   END                       

Espero alguien pueda ayudarme, ya hice todo lo que pude encontrar en foros e internet


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #1 en: 04 de Marzo de 2018, 19:46:53 »
Si te podes explicar un poco mejor en el funcionamiento seria ideal.

Hasta ahora lo unico que me quedo claro es que parpadea cada medio segundo RC0

Cual es el objetivo de RB0?
Cual es el objetivo de RB1?

Desconectado Rayloool

  • PIC10
  • *
  • Mensajes: 5
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #2 en: 04 de Marzo de 2018, 19:53:29 »
Si te podes explicar un poco mejor en el funcionamiento seria ideal.

Hasta ahora lo unico que me quedo claro es que parpadea cada medio segundo RC0

Cual es el objetivo de RB0?
Cual es el objetivo de RB1?
No se si esta es la forma de responder, lo siento si lo estoy haciendo mal "soy nuevo en el foro" RB0 creara la interrupcion y hara que parpadee tres veces mas una vez que se suelta RB0, mientras se mantiene presionado el led no tiene que hecer nada solo esperar hasta que se suelte para hacer los 3 parpadeos y luego apagarse, hasta que RB1 se encienda y pueda salir de el bucle y limpiar INTF para que pueda salir de la interrupcion y regresar al programa

Desconectado Rayloool

  • PIC10
  • *
  • Mensajes: 5
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #3 en: 04 de Marzo de 2018, 22:09:10 »
Lo siento mucho tuve un error grave en una parte

ATIENDE
   BTFSC   PORTB,0
   GOTO   ATIENDE
   BTFSS   PORTB,1
   CALL   PROGRAMA
   BTFSS   PORTB,1
   CALL   PROGRAMA
   BTFSS   PORTB,1
   CALL   PROGRAMA
   BTFSS   PORTB,1
AQUI
   BCF      PORTC,0
   BTFSS   PORTB,1
   GOTO   AQUI
   BCF      INTCON,INTF
   RETFIE
mil disculpas no me di cuenta por tantas pruebas que eh hecho :( aun asi no me reconoce la interrupcion

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #4 en: 04 de Marzo de 2018, 23:55:34 »
Si entendi correctamente:

Al soltarse RB0: Debe parpadear 3 veces.
Si se presiona y suelta RB0 finalizado el parpadeo, no debe pasar nada.
Si se presiona y suelta RB0 mientra parpadea, no debe pasar nada.
Si se presiona RB1 luego de lo anterior, debe habilitar a RB0 a hacer otros 3 parpadeos
Si se presiona RB1 mientras hace los parpadeos: ??????? voy a suponer que debe terminar los parpadeos
Si se presiona RB1 antes de que RB0 haga algo, entonces no pasa nada.

me voy a basar en lo que entendi.
Bueno te explico masomenos como va el tema de las interrupciones:

- Nunca podes tener un loop que no salga (o tener un boton como RB1 con ese goto ) dentro de la interrupcion. Si haces eso, entonces no tiene tener una interrupcion. Ya que estarias bloqueando las otras posibles interrupciones ( en caso que tengas varias) tal ves aca no te afecte, pero en si mejor acostumbrarse a eso.

- Te falta el guardar el contexto y restablecerlo al salir , con contexto me refiero a los registros STATUS, W y PCLATH, ya que si vuelve al programa principal luego de que vos cambiaste los valores de W y STATUS (valores que trabajste en la interrupcion ) no van a ser los mismos que venia usando el programa principal. Microchip ofrece el codigo, busca W_TEMP en el datasheet y lo vas a encontrar.
Esto que nombre te va a llevar a tener un solo RETFIE.

Respecto al programa, no se si vale la pena usar la interrupcion para este ejemplo, pero creo que estas intentando hacerlo asi. Asi que vamos a seguir con esa idea.

Primero vamos a la base:


Código: ASM
  1. list      p=16f886  
  2.    #include   <p16f886.inc>  
  3.  
  4.    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
  5.    __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
  6.  
  7.  
  8.    CBLOCK 0x70
  9.    W_TEMP         ; 0x70
  10.    STATUS_TEMP    ; 0x71
  11.    ENDC
  12.  
  13.    ORG     0x000  
  14.    GOTO    INICIO
  15.    ORG     0X004
  16.    GOTO    INTERRUPCION
  17.  
  18. INICIO
  19.  
  20.    ;Configuracion de puertos/modulos
  21.    ; Inicializacion de cualquier variable
  22.  
  23. LOOP
  24.    ; Loop principal
  25.    GOTO    LOOP
  26.  
  27.  
  28. INTERRUPCION
  29.    ; Guardo
  30.    MOVWF W_TEMP
  31.    SWAPF STATUS,W
  32.    MOVWF STATUS_TEMP
  33.  
  34.    ; Comienza codigo de interrupcion
  35.  
  36.    BTFSC INTCON, INTF
  37.    CALL  INT_BOTON_RB0
  38.  
  39.    ; Fin de codigo de interrupcion
  40.    ; Reestablezco
  41.    
  42.    SWAPF STATUS_TEMP,W
  43.    MOVWF STATUS
  44.    SWAPF W_TEMP,F
  45.    SWAPF W_TEMP,W
  46.    RETFIE
  47.  
  48.    END


De aca debemos pensar el programa

La seccion de configuracion me parece correcta. Por lo que no deberia tocarse. Pero lo demas hay que pasarle una repasada.

En la interrupcion tenemos 2 casos a tener en cuenta:

- Cuando se presiona ( supongamos que va a 0V al presionarlo ) entonces es cuadno se detecta un flanco descendente. Este no nos interesa para nada.
- Cuando se suelta, si seguimos con el la idea, entonces al soltarlo tenemos un flanco ascendente. Este si nos interesa. Asi que estaria bien configurado.

Una ves detectado el boton, podriamos usar un bit de algun registro para saber si tenemos permitido hacer o no los parpadeos.

Vamos a crear un registro llamado BANDERAS el cual el bit 0 va a indicar si debe hacerse o no los parpadeos.

La interrupcion es simple... Es activar este bit y desactivar la interrupcion de RB0

Código: ASM
  1. INT_BOTON_RB0
  2.    BCF      INTCON, INTF
  3.    BTFSC    BANDERAS, 0
  4.    GOTO     ACTIVO_TODAVIA    ;Por si se quiere agregar algun codigo que haga algo si es que se suelta mientras esta parpadeando
  5.    BSF      BANDERAS, 0       ; Activo el bit para saber que ya puede parpadear
  6.    BCF      INTCON, INTE      ; Desactivo las interrupciones de RB0
  7.    MOVLW    0x06
  8.    MOVWF    CONTADOR          ; Recargo el contador de parpadeos
  9. ACTIVO_TODAVIA  
  10.    RETURN

Por otra parte necesitamos hacer el Loop principal, en este loop vamos a leer RB1 y actuar en consecuencia, y ademas hacer el parpadeo.


Código: ASM
  1. LOOP
  2.    CALL LEER_RB1
  3.    CALL LED_TMR
  4.    GOTO LOOP

Respecto a RB1:
Si estan desactivadas las interrupciones de RB0 esto nos dice que ya se presiono antes RB1, por lo que no nos interesa hacer nada en ese caso. Luego observamos si esta presionado RB1, si lo esta, procedemos a reactivar las interrupciones.

Código: ASM
  1. LEER_RB1
  2.    BTFSS    INTCON, INTE
  3.    RETURN                  ; En caso que no este activado las interrupciones ( se presione 2 veces RB1)
  4.    BTFSS    PORTB, 1       ; Se presiono RB1
  5.    RETURN  
  6.    BCF      INTCON, INTF   ; Limpio bandera
  7.    BSF      INTCON, INTE   ; Activo nuevamente las interrupciones.
  8.    RETURN

Respecto al parpadeo:
  Aca dijimos que ibamos a usar el bit 0 de BANDERAS para saber si debiamos parpadear o no. Por eso mismo lo primero que leemos es si este bit nos habilita o no a parpadear.
De alli si esta habilitado necesitamos saber si paso o no el tiempo de parpadeo, si no paso que salga y pruebe leer RB1 y que vuelva.
Si se cumplio el tiempo, cambiamos el estado de RC0, recargamos el Timer, y borramos la bandera del Timer, ademas tenemos que llevar la cuenta de cuantas veces cambiamos la salida, por eso usamos otro registro llamado CONTADOR.

Mientras no se termina de parpadear, esto sigue, cuando se termina, pone a 0 el bit de BANDERAS, para indicar que termino y no debe entrar mas. Y la unica forma que se habilite es que se presione RB1 (para activar las interrupciones) y que luego se presione/suelte RB0 para activar nuevamente este bit.

Código: ASM
  1. LED_TMR
  2.    BTFSS    BANDERAS, 0    ; Tengo que  parpadear ?
  3.    RETURN
  4.    BTFSS    INTCON, T0IF   ; Paso el tiempo?
  5.    RETURN                  ; No paso el tiempo, vuelvo
  6.    MOVLW    0x01
  7.    XORWF    PORTC          ; Invierto el estado de RC0
  8.    MOVLW    .12
  9.    MOVWF    TMR0           ; Recargo el timer
  10.    BCF      INTCON, T0IF   ; Limpio bandera
  11.    DECFSZ   CONTADOR, F    ; Decremetno la cantidad de parpadeos
  12.    RETURN
  13.    ;Aca llegamos cuando se termino contador
  14.    BCF      BANDERAS, 0    ; Se terminaron los 3 parpadeos, entonces procedo a apagar la funcion de parpadeo
  15.    RETURN

Desconectado Rayloool

  • PIC10
  • *
  • Mensajes: 5
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #5 en: 05 de Marzo de 2018, 02:14:06 »
Si entendi correctamente:

Al soltarse RB0: Debe parpadear 3 veces.
Si se presiona y suelta RB0 finalizado el parpadeo, no debe pasar nada.
Si se presiona y suelta RB0 mientra parpadea, no debe pasar nada.
Si se presiona RB1 luego de lo anterior, debe habilitar a RB0 a hacer otros 3 parpadeos
Si se presiona RB1 mientras hace los parpadeos: ??????? voy a suponer que debe terminar los parpadeos
Si se presiona RB1 antes de que RB0 haga algo, entonces no pasa nada.

me voy a basar en lo que entendi.
Bueno te explico masomenos como va el tema de las interrupciones:

- Nunca podes tener un loop que no salga (o tener un boton como RB1 con ese goto ) dentro de la interrupcion. Si haces eso, entonces no tiene tener una interrupcion. Ya que estarias bloqueando las otras posibles interrupciones ( en caso que tengas varias) tal ves aca no te afecte, pero en si mejor acostumbrarse a eso.

- Te falta el guardar el contexto y restablecerlo al salir , con contexto me refiero a los registros STATUS, W y PCLATH, ya que si vuelve al programa principal luego de que vos cambiaste los valores de W y STATUS (valores que trabajste en la interrupcion ) no van a ser los mismos que venia usando el programa principal. Microchip ofrece el codigo, busca W_TEMP en el datasheet y lo vas a encontrar.
Esto que nombre te va a llevar a tener un solo RETFIE.

Respecto al programa, no se si vale la pena usar la interrupcion para este ejemplo, pero creo que estas intentando hacerlo asi. Asi que vamos a seguir con esa idea.

Primero vamos a la base:


Código: ASM
  1. list      p=16f886  
  2.    #include   <p16f886.inc>  
  3.  
  4.    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
  5.    __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
  6.  
  7.  
  8.    CBLOCK 0x70
  9.    W_TEMP         ; 0x70
  10.    STATUS_TEMP    ; 0x71
  11.    ENDC
  12.  
  13.    ORG     0x000  
  14.    GOTO    INICIO
  15.    ORG     0X004
  16.    GOTO    INTERRUPCION
  17.  
  18. INICIO
  19.  
  20.    ;Configuracion de puertos/modulos
  21.    ; Inicializacion de cualquier variable
  22.  
  23. LOOP
  24.    ; Loop principal
  25.    GOTO    LOOP
  26.  
  27.  
  28. INTERRUPCION
  29.    ; Guardo
  30.    MOVWF W_TEMP
  31.    SWAPF STATUS,W
  32.    MOVWF STATUS_TEMP
  33.  
  34.    ; Comienza codigo de interrupcion
  35.  
  36.    BTFSC INTCON, INTF
  37.    CALL  INT_BOTON_RB0
  38.  
  39.    ; Fin de codigo de interrupcion
  40.    ; Reestablezco
  41.    
  42.    SWAPF STATUS_TEMP,W
  43.    MOVWF STATUS
  44.    SWAPF W_TEMP,F
  45.    SWAPF W_TEMP,W
  46.    RETFIE
  47.  
  48.    END


De aca debemos pensar el programa

La seccion de configuracion me parece correcta. Por lo que no deberia tocarse. Pero lo demas hay que pasarle una repasada.

En la interrupcion tenemos 2 casos a tener en cuenta:

- Cuando se presiona ( supongamos que va a 0V al presionarlo ) entonces es cuadno se detecta un flanco descendente. Este no nos interesa para nada.
- Cuando se suelta, si seguimos con el la idea, entonces al soltarlo tenemos un flanco ascendente. Este si nos interesa. Asi que estaria bien configurado.

Una ves detectado el boton, podriamos usar un bit de algun registro para saber si tenemos permitido hacer o no los parpadeos.

Vamos a crear un registro llamado BANDERAS el cual el bit 0 va a indicar si debe hacerse o no los parpadeos.

La interrupcion es simple... Es activar este bit y desactivar la interrupcion de RB0

Código: ASM
  1. INT_BOTON_RB0
  2.    BCF      INTCON, INTF
  3.    BTFSC    BANDERAS, 0
  4.    GOTO     ACTIVO_TODAVIA    ;Por si se quiere agregar algun codigo que haga algo si es que se suelta mientras esta parpadeando
  5.    BSF      BANDERAS, 0       ; Activo el bit para saber que ya puede parpadear
  6.    BCF      INTCON, INTE      ; Desactivo las interrupciones de RB0
  7.    MOVLW    0x06
  8.    MOVWF    CONTADOR          ; Recargo el contador de parpadeos
  9. ACTIVO_TODAVIA  
  10.    RETURN

Por otra parte necesitamos hacer el Loop principal, en este loop vamos a leer RB1 y actuar en consecuencia, y ademas hacer el parpadeo.


Código: ASM
  1. LOOP
  2.    CALL LEER_RB1
  3.    CALL LED_TMR
  4.    GOTO LOOP

Respecto a RB1:
Si estan desactivadas las interrupciones de RB0 esto nos dice que ya se presiono antes RB1, por lo que no nos interesa hacer nada en ese caso. Luego observamos si esta presionado RB1, si lo esta, procedemos a reactivar las interrupciones.

Código: ASM
  1. LEER_RB1
  2.    BTFSS    INTCON, INTE
  3.    RETURN                  ; En caso que no este activado las interrupciones ( se presione 2 veces RB1)
  4.    BTFSS    PORTB, 1       ; Se presiono RB1
  5.    RETURN  
  6.    BCF      INTCON, INTF   ; Limpio bandera
  7.    BSF      INTCON, INTE   ; Activo nuevamente las interrupciones.
  8.    RETURN

Respecto al parpadeo:
  Aca dijimos que ibamos a usar el bit 0 de BANDERAS para saber si debiamos parpadear o no. Por eso mismo lo primero que leemos es si este bit nos habilita o no a parpadear.
De alli si esta habilitado necesitamos saber si paso o no el tiempo de parpadeo, si no paso que salga y pruebe leer RB1 y que vuelva.
Si se cumplio el tiempo, cambiamos el estado de RC0, recargamos el Timer, y borramos la bandera del Timer, ademas tenemos que llevar la cuenta de cuantas veces cambiamos la salida, por eso usamos otro registro llamado CONTADOR.

Mientras no se termina de parpadear, esto sigue, cuando se termina, pone a 0 el bit de BANDERAS, para indicar que termino y no debe entrar mas. Y la unica forma que se habilite es que se presione RB1 (para activar las interrupciones) y que luego se presione/suelte RB0 para activar nuevamente este bit.

Código: ASM
  1. LED_TMR
  2.    BTFSS    BANDERAS, 0    ; Tengo que  parpadear ?
  3.    RETURN
  4.    BTFSS    INTCON, T0IF   ; Paso el tiempo?
  5.    RETURN                  ; No paso el tiempo, vuelvo
  6.    MOVLW    0x01
  7.    XORWF    PORTC          ; Invierto el estado de RC0
  8.    MOVLW    .12
  9.    MOVWF    TMR0           ; Recargo el timer
  10.    BCF      INTCON, T0IF   ; Limpio bandera
  11.    DECFSZ   CONTADOR, F    ; Decremetno la cantidad de parpadeos
  12.    RETURN
  13.    ;Aca llegamos cuando se termino contador
  14.    BCF      BANDERAS, 0    ; Se terminaron los 3 parpadeos, entonces procedo a apagar la funcion de parpadeo
  15.    RETURN
En general no era eso, creo que me explique pésimo, el programa en si lo que hace es que de arranque sin interrupción esta parpadeando continuamente a .5 segundos, mientras RB0 se mantiene presionado, el bit de RC0 esta en 0, cuando se suelta RB0 parpadea 3 veces y se apaga a través de RC0, si RB1 es presionado, mientras se mantiene presionado el bit RC0 sigue apagado, cuando se suelta es cuando vuelve a parpadear continuamente esperando que RB0 sea presionado, mi problema principal es que no activa la interrupcion no se por que pero por mas que presiono RB0 no consigo que provoque interrupcion, incluso probe con interrupciones mas simples como simplemente encender el led y no consigo que la interrupcion se de, respecto a las correcciones lo agradezco mucho creo que ahora puedo corregir a mejor mi programa solo que sigo con el mismo problema, no se da la interrupcion :( perdon.

Desconectado Rayloool

  • PIC10
  • *
  • Mensajes: 5
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #6 en: 05 de Marzo de 2018, 12:24:34 »
Al final vi que mi problema no radicaba en la interrupción si no que a pesar de activar el pull up no me lo reconocia por lo tanto no estaba cambiando de estado en RB0 ni RB1 lo arregle poniendole otras resistencias conectadas a negativo a los push, tocara investigar sobre ello pero creo que puedo dar este tema por solucionado, lo siento si les hice perder su tiempo :/ como cierro el tema?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:No logro hacer que funcionen las interrupciones por RB0
« Respuesta #7 en: 05 de Marzo de 2018, 14:13:54 »
Ya esta solucionado, no hay problema, no hace falta cerrarlo.


 

anything