Autor Tema: programa entra a interrupción pero no sale de ella  (Leído 3771 veces)

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

Desconectado amadeuscito

  • PIC10
  • *
  • Mensajes: 7
programa entra a interrupción pero no sale de ella
« en: 06 de Diciembre de 2008, 18:55:45 »
Hola amigos, lo que pasa es que tengo un programa el cual funciona como yo esperaría, sólo que al momento de atender las interrupciones (rb7:rb4), entra en dicha interrupción y la ejecuta y todo, sólo que al final ya no sale de la interrupción, o a lo mejor sí sale, pero ya no sigue ejecutando el programa donde se había quedado anteriormente.

Guardo mis variables W y STATUS y PCLATH (las vuelvo a recuperar al final). En dicha interrupción utilizo call`s, goto`s, utilizo el tmr0 pero desactivé su interrupción por desbordamiento. Les pongo el código.

Uso el mplab 7.50 y grabo mi programa con el winpic800, mi grabador es un ponyprog II o algo así, compatible con jdm. Mi pic es un 16f877a.

He estado pensando que a lo mejor pudieran estar mal mis fuses, no lo se bien, uitilzo un cristal de 8MHZ.

Mi programa es el siguiente:

Código: [Seleccionar]
LIST p=16f877A
INCLUDE<p16f877A.inc>
__config b'11111101110010'
   
dato equ 0x79
abc equ 0x7A
conts equ 0x75 ;//contador ascendente para las series
conts2 equ 0x76 ;//contador descendente para las series
veces equ 0x77 ;//para el timer0
veloci equ 0x78 ;//velocidad del timer0
pclath_temp EQU 0x7C
w_temp EQU 0x7D ; variable used for context saving
status_temp EQU 0x7E ; variable used for context saving

ORG 0
goto uno
ORG 4
movf PORTB,W
movwf abc
bcf INTCON,RBIF
MOVWF    w_temp           ;Copy W to TEMP register
SWAPF    STATUS, W         ;Swap status to be saved into W
CLRF     STATUS           ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF    status_temp      ;Save status to bank zero STATUS_TEMP register
MOVF     PCLATH, W      ;Only required if using page 1
MOVWF    pclath_temp      ;Save PCLATH into W
CLRF     PCLATH           ;Page zero, regardless of current page
goto teclas
;************************************************************
teclas:
call time3
call time3
col4: btfsc PORTB,4
goto col4
col5: btfsc PORTB,5
goto col5
col6: btfsc PORTB,6
goto col6
col7: btfsc PORTB,7
goto col7
movlw 0x55
movwf PORTC
call time2
call time2
call time2
call time2

clrf conts
c1: incf conts,F
movf conts,W
call auto2
movwf PORTC
call time2
btfsc conts,3
goto c1
btfsc conts,2
goto c1
btfsc conts,1
goto c1
btfsc conts,0
goto c1
c2: movf conts2,W
call auto2
movwf PORTC
call time2
decfsz conts2,F
goto c2

MOVF     pclath_temp, W  ;Restore PCLATH
MOVWF    PCLATH          ;Move W into PCLATH
SWAPF    status_temp, W  ;Swap STATUS_TEMP register into W
                         ;(sets bank to original state)
MOVWF    STATUS         ;Move W into STATUS register
SWAPF    w_temp, F ;Swap W_TEMP
SWAPF    w_temp, W      ;Swap W_TEMP into W
bcf INTCON,INTF
retfie                    ; return from interrupt
auto1: ;//auto increible1
ADDWF PCL,F
RETLW 0X00
RETLW 0X01 ;//1
RETLW 0X02
RETLW 0X04
RETLW 0X08
RETLW 0X10
RETLW 0X20
RETLW 0X40
goto aa00
goto aa01 ;//para puerto D
movlw 02
movwf PORTD
decf conts,W
movwf conts2
clrf conts
retlw 00
aa01:
movlw 01
movwf PORTD
retlw 00
aa00
movlw 00
movwf PORTD
RETLW 0X80
auto2: ;//auto increible 2
ADDWF PCL,F
RETLW 0X00
RETLW 0x01
RETLW 0X03
RETLW 0X06
RETLW 0X0C
RETLW 0X18
RETLW 0X30
RETLW 0X60
goto bb00
goto bb01 ;//al mismo tiempo con puerto D
goto bb03
goto bb04
movlw 02
movwf PORTD
decf conts,W
movwf conts2
clrf conts
retlw 00
bb04: ;//aqui solo puerto D
movlw 01
movwf PORTD
retlw 00
bb01:
movlw 01
movwf PORTD
retlw 80
bb03:
movlw 03
movwf PORTD
retlw 00
bb00:
clrf PORTD
RETLW 0XC0

uno: bsf STATUS,5
movlw b'11110000'
movwf TRISB ;// bits como entrada rb4-rb7
clrf TRISC ;// todo el puerto C como salida
clrf TRISD ;// todo el puerto d como salida
movlw 0x87
movwf OPTION_REG ;// para timer0
movlw b'10001000'
movwf INTCON ;// para interrupcion de puerto b
clrf STATUS
movlw 0x88
movwf INTCON ;// para interrupcion de puerto b
clrf PORTC ;// limpiamos C y d
clrf PORTD
movlw 0x00
movwf dato
movlw d'21'
movwf veloci
;***********************************************************
inicio:
movlw 0x0F ;// mandamos unos x rb0-rb3
movwf PORTB
movf dato,W
addwf PCL,F
goto serie01
goto serie02
serie01: ;//auto increible 1
movlw 0x00
movwf conts
lup1: incf conts,F
movf conts,W
call auto1
movwf PORTC
call time3
btfsc conts,3
goto lup1
btfsc conts,2
goto lup1
btfsc conts,1
goto lup1
btfsc conts,0
goto lup1
lup2: movf conts2,W
call auto1
movwf PORTC
call time3
decfsz conts2,F
goto lup2
goto inicio

serie02:
movlw 0xff
movwf PORTC ;// li
clrf PORTD
goto inicio


;************************************************************

time2:
movlw d'09'
movwf veces
pris: movf veloci,W
movwf TMR0
ess: btfss INTCON,2
goto ess
bcf INTCON,2
decfsz veces,F
goto pris
return
time3:
movlw d'01'
movwf veces
sir: movf veloci,W
movwf TMR0
sse: btfss INTCON,2
goto sse
bcf INTCON,2
decfsz veces,F
goto sir
return
END



Los fuses que me da el winpic800 son:

OSC:         HS
WRT:        OFF
WDTEN:    OFF
PWRTEN:   ON
BOREN:     ON
LVP:          OFF
CPD:         OFF
CP:           OFF
DEBUG:     OFF

O SEA:          0X2007:3F72

El ide que me da es:
FFFF

Antes grababa con el ic-prog pero como me quemo varios pic´s, tome la recomendación de algun otro post de aquí para cambiarlo por el winpic800. Y éste último funciona super bien...

Desconectado Javicho

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 570
Re: programa entra a interrupción pero no sale de ella
« Respuesta #1 en: 06 de Diciembre de 2008, 19:23:41 »
Hola:

En el inicio puedes hacer esto para que te sea mas facil cambiar los fusibles:

   LIST P=16F877A
   include <p16F877A.inc>
   errorlevel  -302      ;suprime mensaje: " Register in operand not in bank 0.  Ensure that bank bits are correct "
   errorlevel  -306      ;suprime mensaje: " Crossing page boundary -- ensure page bits are set."
   __CONFIG  _BODEN_OFF&_CP_OFF&_WRT_OFF&_PWRTE_ON&_WDT_OFF&_XT_OSC&_DEBUG_OFF&_CPD_OFF&_LVP_OFF

Colocas On/Off según convenga.

Por otro lado en el RSI primero guarda el registro w, status, etc y despues recien lees el puertoB y lo demas. Por seguridad es mejor que cuando ingreses al RSI leas el bit RBIF para que estes bien seguro de que la interrupción se produjo por este caso y no por ruido u otro caso.

Tambien recuerda que este pic tiene modulo comparador asi que tienes que desactivarlo si no lo vas a usar (CMCON=7: comparadores desactivados), lo mismo en el caso de los conversores analogos que vienen habilitados por defecto (ADCON1=6 modulo AD desactivado si no me equivoco).

Javicho.

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: programa entra a interrupción pero no sale de ella
« Respuesta #2 en: 06 de Diciembre de 2008, 20:47:23 »
Como te dice Javicho, debes guardar los registros de trabajo apenas entras en la interrupcion y antes de ejecutar los testeos...

Tu pones:
Código: [Seleccionar]
                movf PORTB,W
movwf abc
bcf INTCON,RBIF
MOVWF    w_temp           ;Copy W to TEMP register
SWAPF    STATUS, W         ;Swap status to be saved into W
CLRF     STATUS           ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF    status_temp      ;Save status to bank zero STATUS_TEMP register
MOVF     PCLATH, W      ;Only required if using page 1
MOVWF    pclath_temp      ;Save PCLATH into W
CLRF     PCLATH           ;Page zero, regardless of current page

y deberias poner:

Código: [Seleccionar]
MOVWF    w_temp           ;Copy W to TEMP register
SWAPF    STATUS, W         ;Swap status to be saved into W
CLRF     STATUS           ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF    status_temp      ;Save status to bank zero STATUS_TEMP register
MOVF     PCLATH, W      ;Only required if using page 1
MOVWF    pclath_temp      ;Save PCLATH into W
CLRF     PCLATH           ;Page zero, regardless of current page
                movf     PORTB,W
movwf abc
bcf INTCON,RBIF
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado amadeuscito

  • PIC10
  • *
  • Mensajes: 7
Re: programa entra a interrupción pero no sale de ella
« Respuesta #3 en: 06 de Diciembre de 2008, 20:55:52 »
Hola Javicho y MGLSOFT, gracias por sus comentarios y sugerencias, voy a cambiar el código según sus recomendaciones.

Por cierto, comento que borré la parte de la interrupción, en la que es un bucle, le dejé las llamadas al timer0 y la comprobación de si ya se soltó la tecla o no.

Con éste pedazo de menos, el programa hace lo que se espera, SALE DE LA INTERRUPCÓN, sin embargo, si se le pone este pedazo, lo ejecuta bien pero al final cuando termina de ejecutarlo (muy bien por cierto), no sale de la interrupción.

Alguna sugerencia? Me interesa que éste código se ejecute dentro, sino igual voy a tener que reestructurar todo mi programa, pero por lo menos quisiera saber en qué estoy mal. Muchas gracias por sus sugerencias y recomendaciones...

         clrf   conts
   c1:        incf   conts,F
         movf   conts,W
         call   auto2
         movwf   PORTC
         call   time2
         btfsc   conts,3
         goto   c1
         btfsc   conts,2
         goto   c1
         btfsc   conts,1
         goto   c1
         btfsc   conts,0
         goto   c1
   c2:        movf   conts2,W
         call   auto2
         movwf   PORTC
         call   time2
         decfsz   conts2,F
         goto   c2

Voy a probar desactivando lo que me recomiendas Javicho, igual voy a mejorar su funcionamiento con las recomendaciones de los dos.

Desconectado Javicho

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 570
Re: programa entra a interrupción pero no sale de ella
« Respuesta #4 en: 06 de Diciembre de 2008, 21:21:04 »
En time2 estás escribiendo al Timer0, recuerda que si estas usando el prescaler éste se borra cuando escribes un valor en el timer0 por eso luego de escribir un valor en est temporizador debes volver a cargar el valor del prescaler.

Por otro lado, en auto2 si no me equivoco tienes una tabla, la cual tal vez esté arriba de las primeras 255 lineas de programa esto significa que el PCLATH debe ser 1 si estas entre la linea 256 y la 511 de la memoria de programa, esto puede darse ya que cuando colocas el resto del codigo las posiciones de las lineas donde esta la tabla tambien suben, mejor escribe el valor adecuado al PCLATH y recien llama a la tabla, tal vez por eso no sale del RSI porque cuando ingresas a la tabla y no has configurado bien el PCLATH el flujo del programa se va a quien sabe donde, solo Dios lo sabe.

Javicho.

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: programa entra a interrupción pero no sale de ella
« Respuesta #5 en: 06 de Diciembre de 2008, 21:23:05 »
Disculpa la preguntonta, pero por que razon quieres hacer ejecutar este lazo dentro de la interrupcion??
Porque no marcas banderas y apenas sales lo ejecutas??
Es muy peligroso el uso de goto y call dentro de una interrupcion, porque ayuda mucho a perder el control del programa....

De hecho asi te pasa. :mrgreen:

Je. je..
Casi a la vez contestamos con Javicho.. :D
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: programa entra a interrupción pero no sale de ella
« Respuesta #6 en: 06 de Diciembre de 2008, 22:44:09 »
Bueno, debo decir que tu forma de programar es sumamente compleja. Esos bucles que realizas son bastante "peligrosos", aunque funcionan bien. Penden de un hilo. Es decir: por lo que he visto en tu código lo has complejizado tanto que si quitas una línea o pretendes modificarlo algún día deberás tener extremo cuidado porque está todo hartamente pensado y el menor cambio haría estragos.  Aún así, el trozo de código al cual le echas la culpa funciona correctamente. El problema por el cual no sale de la interrupción es bastante sencillo(creo) y no tiene que ver con esos bucles en sí. Es que al estar los bucles(juego de luces) el uC tarda más tiempo en salir de la subrutina de interr. y se producen cambios en el estado del nibble alto del puertob(es decir, las columnas del teclado) que hacen que el flag de cambio de puertob vuelva a activarse. La solución? Limpiar el flag RBIF y leer el puertob exáctamente antes del retfie, es decir: debería quedar así:
       ;...
       ;...
       movf portb,w
       bcf    INTCON,RBIF
       retfie


El problema en la forma en la que lo estás haciendo es que actualmente mientras se ejecuta la interrupción (lo que es bastante tiempo si tenemos en cuenta que todo el juego de luces transcurre dentro) no sos capaz de detectar cambios en el teclado. Es decir que no se puede cancelar o cambiar la secuencia actual, etc hasta que la secuencia no haya finalizado y el uC haya salido de la interr. Si bien es posible cambiar el codigo para que dentro de la misma interr. puedas detectar las teclas, te recomiendo que migres hacia la idea de MGLSOFT y sólo actives los flags dentro de la interr y en el bucle principal del programa revises dicho flags y ejecutes el comando o secuencia que corresponda.

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado amadeuscito

  • PIC10
  • *
  • Mensajes: 7
Re: programa entra a interrupción pero no sale de ella
« Respuesta #7 en: 08 de Diciembre de 2008, 14:53:15 »
Primeramente, muchísimas gracias por sus comentarios.

Tengo otro programa un poco más complejo de éste, la función que realiza es que ejecuta varios efectos de luces, éstos efectos se pueden seleccionar con un teclado 4x4 (primera duda BrunoK, recuerdas) mediante interrupción, ya que al principio se está ejecutando algún efecto (se ejectua y regresa al inicio del programa para ver el valor de una variable, ésta variable decide qué efecto se va a ejecutar, mediante una tabla). Mientras se ejecuta dicho efecto, si surge una interrupción, ésta verifica de qué tecla se trata (de 16 posibles) y guarda un valor en la variable (la que ya dije que decide el efecto a ejecutar mediante una tabla). Sale de la interrupción, termina la secuencia de la luz donde se había quedado e igualmente regresa al inicio para verificar el nuevo valor de la variable (movf xxxxx    addwf, pcl....), yendo (goto) según su valor a una posición x (algún efecto diferente).

Tuve problemas con ése programa, inicialmente con la interrupción, pero ahora de lo que les comento (no sale de la interrupción).

Por esta razón hice un programa más pequeño pero con las mismas situaciones (de la interrupción) y pues si resolvía éste programita, sabría cómo atacar el otro.

Ya probe dicho programa como dice BrunoF, pero el resultado es el mismo.

Entro en la iinterrupción y guardo luego luego mis variables como aconseja Javicho y MGLSOFT, pero sigue igual. El timer no me da problemas, pues lo ejecuto una y otra vez y sin embargo los efectos tienen la misma duración. Es importante tu recomendación Javicho, voy a estudiar un poco más a fondo el timer0.

Como les comenté, sin éste pedazo de código en la interrupción, el programa hace exactamente lo que tiene que hacer. Pienso que como dice MGLSOFT, el problema radicaría en la cantidad de goto´s y call´s dentro de la interrupción. E igualmente voy a tomar su consejo de activar sólo las flags dentro de la interrupción.

Cuando termine mi programa, se los paso para que lo chequen. Espero no sea tan complejo para entonces.

Gracias por sus comentarios.

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: programa entra a interrupción pero no sale de ella
« Respuesta #8 en: 08 de Diciembre de 2008, 18:26:53 »
En este programa que has puesto amadeuscito, falta la etiqueta serie01, lo llamas a travez de un goto.
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado catk

  • PIC10
  • *
  • Mensajes: 13
Re: programa entra a interrupción pero no sale de ella
« Respuesta #9 en: 27 de Marzo de 2009, 12:30:58 »
Amigos tengo un problema similar:
A continuación pongo el código de mi programa, pero mi problema es: Después que se genera la interrupción necesito esperar un tiempo (20 segundois) pero si durante esos 20 segundos se produce una interrupcion necesito que se suspenda, pero hasta el momento no lo he logrado algo me falta pero no veo donde puede estar mi problema.
De antemano gracias al que de con mi problema.

Código: [Seleccionar]



__CONFIG   _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

LIST    P=16F84A

INCLUDE  <P16F84A.INC>


CBLOCK   0x0C

ENDC

;-------Configuración de puertos-------

ORG 0x00               
GOTO inicio
ORG 0x04         
GOTO ISR
ORG 0X05

inicio BSF STATUS,RP0       ; configurando puertos
MOVLW 0x01          ; carga w con 0000 0001
MOVWF TRISB          ; RB0/INT es entrada
BCF OPTION_REG,6   ; seleccionamos flanco descendente
BCF STATUS,RP0

;-------Habilitación de interrupciones-------

BSF INTCON,GIE      ; habilitamos todas las interrupciones
BSF INTCON,INTE     ; que sean interrupciones externas
CLRF PORTB         ; limpio el puerto B
sueño SLEEP
GOTO sueño                ; Dulces sueños...!!!

;-------------Rutina de servicio de interrupciones-------------

ISR
BTFSC PORTB,0           ; verificamos que suelten el pulsador
GOTO ISR

BTFSC PORTB,1         ; y ahora sí, si el led está a 1
GOTO off_led         ; ire a off_led para apagarlo
GOTO on_led
BCF INTCON,INTF     ; borro bandera de interrupción
RETFIE


on_led
BSF PORTB,1
BCF INTCON,INTF     ; borro bandera de interrupción
call Retardo_10s
BCF PORTB,1
RETFIE

off_led
BCF PORTB,1         ; apago el LED
BCF INTCON,INTF     ; borro bandera de interrupción
RETFIE





INCLUDE   <RETARDOS.INC>

END



Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: programa entra a interrupción pero no sale de ella
« Respuesta #10 en: 27 de Marzo de 2009, 14:50:24 »
Tienes varios errores
Código: [Seleccionar]
        BTFSC PORTB,1         ; y ahora sí, si el led está a 1
GOTO off_led         ; ire a off_led para apagarlo
GOTO on_led
BCF INTCON,INTF     ; borro bandera de interrupción
RETFIE

Por BCF Intcon,intf jamás pasará y tampoco por RETFIE. Por lo que deberás eliminarlos.


Código: [Seleccionar]
sueño SLEEP
GOTO sueño                ; Dulces sueños...!!!

Es recomendable que después de la instrucción Sleep halla un NOP porque el CP lee la instrucción y en el siguiente pulso de reloj lo ejecuta. O sea, cuando recién lee la instrucción goto es cuando ejecuta el SLEEP.

Debe quedar así:

Código: [Seleccionar]
sueño SLEEP
        NOP
GOTO sueño                ; Dulces sueños...!!!

Luego está un poco confuso, porque dentro de una subrutina, está la instrucción call   Retardo_10s y solo se ejecuta una vez, por lo que son 10 segundos transcurridos y se activan las interrupciones.

Ahora bien, si quieres que dentro de los 20 segundos se pueda dar una interrupción, debes habilitar el bit Gie del INTCONT antes de ejecutar el retardo.
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado catk

  • PIC10
  • *
  • Mensajes: 13
Re: programa entra a interrupción pero no sale de ella
« Respuesta #11 en: 27 de Marzo de 2009, 15:14:57 »
Leon Pic primero que todo muchas gracias por tu ayuda.

Te cuento modifique el codigo y nada, le agrege el GIE EQU 07h antes de entrar al retardo y nada las interupciones siguen muertas, mira como lo deje:

Código: [Seleccionar]
on_led
BSF PORTB,1
BCF INTCON,INTF     ; borro bandera de interrupción
GIE EQU 07h
call Retardo_10s
BCF PORTB,1
RETFIE

Tambien intente poniendolo en:

Código: [Seleccionar]
inicio BSF STATUS,RP0       ; configurando puertos
MOVLW 0x01          ; carga w con 0000 0001
MOVWF TRISB          ; RB0/INT es entrada
BCF OPTION_REG,6   ; seleccionamos flanco descendente
BCF STATUS,RP0
GIE EQU 07h



Y nada, donde esta mi problema?
No se si tengo una confucion muy grande con las interrupciones o es simplemente un error de logica en el momento de programar

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: programa entra a interrupción pero no sale de ella
« Respuesta #12 en: 27 de Marzo de 2009, 15:28:46 »
Gie equ 07H no es una instrucción, es una directiva. Está mal. Tienes que poner BSF intcon,GIE. No recuerdo si es necesario ajustar por software al bit INTF del registro INTCON, pero por las dudas, hazlo.

Debería quedar así:
Código: [Seleccionar]
on_led
BSF PORTB,1
BCF INTCON,INTF     ; borro bandera de interrupción
        BSF   INTCON,GIE
call Retardo_10s
BCF PORTB,1
RETFIE                       ;Como ya habilitaste el bit GIE, puedes reemplazar esta instrucción por RETURN

Código: [Seleccionar]
inicio BSF STATUS,RP0       ; configurando puertos
MOVLW 0x01          ; carga w con 0000 0001
MOVWF TRISB          ; RB0/INT es entrada
BCF OPTION_REG,6   ; seleccionamos flanco descendente
BCF STATUS,RP0

;-------Habilitación de interrupciones-------

BSF INTCON,GIE      ; habilitamos todas las interrupciones
BSF INTCON,INTE     ; que sean interrupciones externas
CLRF PORTB         ; limpio el puerto B
sueño SLEEP
        NOP
GOTO sueño                ; Dulces sueños...!!!



Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.


 

anything