Autor Tema: Problema al retornar de la interrupción (SOLUCIONADO)  (Leído 3867 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Problema al retornar de la interrupción (SOLUCIONADO)
« en: 12 de Mayo de 2014, 18:22:51 »
Hola a todos, pues resulta que me hace todo tal y como indica el programa, osea 1º se queda en intermitencia rapida infinitamente , (tengo conectado un led a la patita 2 del portC), y hasta que pulso el interruptor asociado al bit 2 del puerto A.

   ;;;     CLK 4 MHz      

   w      EQU      0h
   f      EQU      1h

   LIST      P=16F1503
   INCLUDE     <P16F1503.INC>

;;;;; 4 Mhz

   CONT   EQU   20H
   CONTMAX   EQU   21H
   CONTMIN   EQU   23H
   RET1   EQU   25H
   RET2   EQU   26H
   RET3   EQU   27H
   
   INDI   EQU   28H
   
         ORG      00H
         GOTO    INICIALIZACION
         
         ORG      04H
         GOTO   ISR



   

;;;;;;;      INICIALIZACION PORT C  
;;;;;;;;      Y  PORTA

INICIALIZACION   NOP

         BANKSEL   OSCCON   ;; RELOJ A 4MHZ   
         MOVLW   6AH
         MOVWF   OSCCON

         BANKSEL   PORTA
         CLRF   PORTA
         BANKSEL   LATA
         CLRF   LATA               
         BANKSEL   ANSELA         ; Puerto A   
         CLRF   ANSELA
         BANKSEL   TRISA
         MOVLW   0Ch            
         MOVWF   TRISA
         

         BANKSEL   PORTC
         CLRF   PORTC
         BANKSEL   LATC
         CLRF   LATC               
         BANKSEL   ANSELC         ; Puerto C   SIN RES. POL.
         CLRF   ANSELC
         BANKSEL   TRISC
         MOVLW   02h
         MOVWF   TRISC



         banksel   OPTION_REG
         CLRF   OPTION_REG
         movlw   0x07
         movwf   OPTION_REG
      

         BANKSEL   WPUA
         MOVLW   0Ch            
         MOVWF   WPUA          ;ACTIVADA, BIT 2, 3

         
         BANKSEL   INTCON   ; Rut. servicio interrupciones
         CLRF   INTCON
         MOVLW   0X88
         MOVWF   INTCON   ;PONER A 1 GIE e IOCIE
         BANKSEL   IOCAN
         CLRF   IOCAN
         BSF      IOCAN,2   ;  a 1 IOCAN2



         BANKSEL   PORTC         

INT.RAPIDA   NOP   
         BSF      PORTC,2
         CALL   DEMORA406  ;;; RUTINA INTERMITENCIA
         BCF      PORTC,2      ;;;;;   RAPIDA   
         CALL   DEMORA406
            
         GOTO    INT.RAPIDA            

ISR         BSF      PORTC,2
         CALL   DEMORA406     ;;; RUTINA INTERMITENCIA
         CALL   DEMORA406      ;;;   LENTA
         CALL   DEMORA406
         BCF      PORTC,2   
         CALL   DEMORA406
         CALL   DEMORA406
         CALL   DEMORA406
         BSF      PORTC,2
         CALL   DEMORA406
         CALL   DEMORA406
         CALL   DEMORA406      
         BCF      PORTC,2


RETORNAR   NOP
         BANKSEL   INTCON   ; Rut. servicio interrupciones
         MOVLW   0X08
         MOVWF   INTCON   ;PONER A 1  IOCIE
         BANKSEL   IOCAN
         BSF      IOCAN,2   ;  a 1 IOCAN2
         BANKSEL   IOCAF
         
         BCF      IOCAF,2      ;  BORRA FLAG
         RETFIE

DEMORA406   MOVLW      10h      ;  CARGA VARIABLES DEMORA
         MOVWF      RET1
         MOVLW      0h
         MOVWF      RET2                                             
         MOVLW      03H
         MOVWF      RET3
DEC2      DECFSZ      RET2    ;  RETARDO DE 406 ms
         GOTO      DEC2    
         DECFSZ      RET1       ;  
         GOTO      DEC2
         DECFSZ      RET3       ;  3 BUCLES
         GOTO      DEC2
      
         RETURN


FIN         NOP
         END


En ese momento, se genera la interrupción , y entra en la rutina de interrupciones ISR, y hace la intermitencia lenta, pero no vuelve a la rutina de int. rapida, sino que, hace el 1,2seg ON, 1,2seg. OFF, 1,2 seg. ON, y se queda apagado.

La verdad no se que me falta poner para que retorne correctamente a la rapida.

Muchas gracias

un saludo
« Última modificación: 13 de Mayo de 2014, 16:24:24 por JoseLuis2801 »

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: Problema al retornar de la interrupción
« Respuesta #1 en: 12 de Mayo de 2014, 19:01:07 »
Hace mucho que no programo; pero por lo poco que lo estudié, te falta restaurar ciertos valores que; previamente, tendrías que haber guardado al momento de entrar a una interrupción.

Buscando en mis programas de asm; encontré un "trabajo" que se hace cuando se entra a la interrupción; y antes de salir de la interrupción.
Es para un micro 16F877:

Código: [Seleccionar]
MOVWF SALVAR_W ;SALVA EL CONTENIDO DE W
SWAPF STATUS,W ;PASAMOS A W STATUS (ES CON SWAPF PARA NO AFECTAR EL BIT Z)
MOVWF SALVAR_STATUS ;SALVA EL CONTENIDO DE STATUS
SWAPF FSR,W ;PASAMOS A W FSR
MOVWF SALVAR_FSR ;SALVA FSR
SWAPF PCLATH,W ;PASAMOS A W PCLATH (Pagina de programa)
MOVWF SALVAR_PCLATH ;SALVA EL CONTENIDO DE PCLATH
BCF STATUS,RP1
BSF STATUS,RP0 ;BANCO 1
SWAPF OPTION_REG,W ;PASAMOS A W OPTION_REG (Bancos)
MOVWF SALVAR_OPTION_REG ;SALVA EL CONTENIDO DE OPTION_REG
BCF STATUS,RP0 ;BANCO 0
BTFSC PIR1,RCIF ;¿SE ACTIVÓ RECEPCIÓN USART?
GOTO RX_USART
BTFSS INTCON,T0IF ;¿HUBO DESBORDE EL TIMER?
GOTO SALIR ;FALSA INTERRUPCIÓN

Código: [Seleccionar]
SALIR BSF STATUS,RP0 ;BANCO 1
SWAPF SALVAR_OPTION_REG,W ;RESTAURA EL VALOR A OPTION_REG
MOVWF OPTION_REG
SWAPF SALVAR_PCLATH,W ;RESTAURA EL VALOR A PCLATH
MOVWF PCLATH
SWAPF SALVAR_FSR,W ;RESTAURA EL VALOR A FSR
MOVWF FSR
SWAPF SALVAR_STATUS,W ;RESTAURA EL VALOR A STATUS
MOVWF STATUS
SWAPF SALVAR_W,F
SWAPF SALVAR_W,W ;RESTAURA EL VALOR A W
BCF PORTC,0 ;APAGAMOS EL LED DE RECEPCIÓN
RETFIE

Presta atención, que primero guardo algunos datos importantes; luego me fijo si lo que tendría que haber producido la interrupción, fue así (en mi caso, son varios; pero verás que uno es interrupción del TMR0)
Cuando termino de hacer lo necesario en la interrupción, restauro todo lo que salvé anteriormente; y luego salgo.

Ahora quiero ir más a tu problema. Cada vez que sale de la interrupción, ¿siempre va al mismo punto; o es aleatorio? Si es aleatorio, al no estar salvando el valor del PCLATH, hace que retorne en cualquier lugar.

¿Lo estás simulando o directamente haces la prueba en placa real?
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción
« Respuesta #2 en: 12 de Mayo de 2014, 19:52:20 »
Gracias, seguro que es algo de eso que comentas,   pero es que como indica esto en el datasheet, en el apartado de las interrupciones :

7.5 Automatic Context Saving
Upon entering an interrupt, the return PC address is
saved on the stack. Additionally, the following registers
are automatically saved in the shadow registers:
• W register
• STATUS register (except for TO and PD)
• BSR register
• FSR registers
• PCLATH register
Upon exiting the Interrupt Service Routine, these registers
are automatically restored. Any modifications to
these registers during the ISR will be lost. If modifications
to any of these registers are desired, the corresponding
shadow register should be modified and the
value will be restored when exiting the ISR. The
shadow registers are available in Bank 31 and are
readable and writable. Depending on the user’s application,
other registers may also need to be saved.

Claro a algún lado retorna pero teoricamente deberia ser a cualquier punto de la rutina INT.RAPIDA, que por otra parte, tiene llamada a la subrutina demora406, con lo cual cuando se produjese la interrupcion, que es cuando pulso el microSWitch, pudiese estar ejecutando los bucles la subrutina406, que ademas seria lo mas normal, pienso, y quizas venga de ahi todo el follón del retorno.

Bueno mañana lo estudio todo mejor, y voy salvado tal y como me indicas, registros.

Directamente en placa lo grabo y lo ejecuto.


Y otra cosa que si que ni idea de XQ, al cabo de unos 55 seg., es como si se resetease el PIC, y vuelve a la intermitencia rapida. Por supuesto yo no hago absolutamente nada.


« Última modificación: 12 de Mayo de 2014, 19:55:56 por JoseLuis2801 »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Problema al retornar de la interrupción
« Respuesta #3 en: 12 de Mayo de 2014, 19:53:45 »
El PIC16F1503, al igual que muchos nuevos de la familia 16F lanzados por Microchip, guardan automáticamente y restauran los registros clave. Por lo tanto el problema no es ese.

La rutina de interrupción suele estar pensada para procesar información rápidamente, no para generar demoras o procesos lentos. Te recomiendo que setees banderas (flags) dentro de la interrupción y las revises y ejecutes acorde en el loop principal, porque por estar haciendo procesos lentos dentro de la ISR, te debés estar perdiendo nuevos eventos que deberían interrumpir.

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 JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción
« Respuesta #4 en: 13 de Mayo de 2014, 04:48:13 »
OK BunoF, XQ con tantas demoras se puede poner a 0 el flag ?

Bueno, como ahora mismo lo único que quiero es ver si lo he hecho bien o no el proceso, voy a utilizar otra patita de salida, y simplemente en la RSI voy a poner un BSF para activar un led y ya esta, seteo flag y vuelvo con el RETFIE.


Os cuento............


Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción
« Respuesta #5 en: 13 de Mayo de 2014, 05:22:24 »
Pues acabo de poner un solo BSF y efectivamente si me vuelve a la rutina de intermitencia lenta.

Posteriormente,  acabo de incluir un solo call demora406, y ya no me retorna.

Pero claro, no sabemos si es mucho tiempo como decias brunoF, o que se empana la saltar a demora406 dentro de la rutina ISR.

Idea, pongo el bucle dentro de la misma ISR, y a ver que pasa.

Os cuento............

Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción
« Respuesta #6 en: 13 de Mayo de 2014, 07:57:00 »
Vale tengo progresos, como dije he conectado otro led rojo  a la patita bit 4 del puerto A.

Led portA es rojo

Led portC es verde.

Pues bien, he incluido la rutina de 406ms dentro de la ISR, y nada, he bajado el tiempo, y nada , he bajado hasta solo 7 microsegundos, se sigue empanando, se queda bloqueado en la propia rutina ya que el led rojo se queda encendido, y el verde se queda en el estado uqe este cuando yo pulso el microSw de la placa, el asociado al bit 2 del portA.    (ver archivo adjunto).

INT.RAPIDA   NOP   
         BSF      PORTC,2
         CALL   DEMORA406  ;;; RUTINA INTERMITENCIA
         BCF      PORTC,2      ;;;;;   RAPIDA   
         CALL   DEMORA406
            
         GOTO    INT.RAPIDA            

ISR         BSF      PORTA,4    ; ENCIENDO LED DE LA RUTINA
                        ;  DE LA INTERRUPCION
         MOVLW      2h      ;  CARGA VARIABLES DEMORA
         MOVWF      RET1   SE BLOQUEA

DEC22      DECFSZ      RET1    ;  RETARDO DE 7 us
         GOTO      DEC22    


RETORNAR   NOP
         BANKSEL   INTCON   ; Rut. servicio interrupciones
         MOVLW   0X88
         MOVWF   INTCON   ;PONER A 1  IOCIE
         BANKSEL   IOCAN
         BSF      IOCAN,2   ;  a 1 IOCAN2
         BANKSEL   IOCAF
         
         BCF      IOCAF,2      ;  BORRA FLAG
         
         RETFIE

Luego cambio ese pequeño bucle por 7 NOPs que abarcan el mismo tiempo, y , se enciende un brevisimo instante el led, y sale de la rutina ISR , ASI QEU RETORNA CORRECTAMENTE y continua con el flash rapido indefinidamente.

ISR         BSF      PORTA,4    ; ENCIENDO LED DE LA RUTINA
                        ;  DE LA INTERRUPCION
 
         NOP
         NOP
         NOP
         NOP
         NOP
         NOP
         NOP

RETORNAR   NOP
         BANKSEL   INTCON   ; Rut. servicio interrupciones
         MOVLW   0X88
         MOVWF   INTCON   ;PONER A 1  IOCIE
         BANKSEL   IOCAN
         BSF      IOCAN,2   ;  a 1 IOCAN2
         BANKSEL   IOCAF
         
         BCF      IOCAF,2      ;  BORRA FLAG
         
         RETFIE




Entonces, no es por el tiempo sino que algo hay en el bucle que no le gusta a la rutina ISR.
Otra cosa es que si el tiempo es grande se dejen de atender otros eventos al estar el bit GIE a 1, eso por supuesto.


« Última modificación: 13 de Mayo de 2014, 08:53:32 por JoseLuis2801 »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Problema al retornar de la interrupción
« Respuesta #7 en: 13 de Mayo de 2014, 09:54:19 »
Hola,

grave complicación rehabilitar las interrupciones dentro de la interrupción. Sólo deberías limpiar el flag. Las Inter no se desconfiguran por ingresar a la isr.
"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 JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción
« Respuesta #8 en: 13 de Mayo de 2014, 11:43:18 »
OK BrunoF, reseteare solo el flag.

...........

Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción (SOLUCINADO)
« Respuesta #9 en: 13 de Mayo de 2014, 16:23:54 »
Vale por fin, he quitado lo que me has dicho y solo he dejado el seteo del flag, y un perfecto, lo que antes no funcionaba con el bucle de 7us. ahora si lo hace, es más lo hace perfecto, XQ ahora si vuelve y ademas se queda encendido el led rojo, como debia ser.  Esta noche os pongo el emlace a un  video.

Por otra parte , una vez esto correcto, voy con las demoras, y he aumentado el tiempo al max. con un bucle, y sigue funcionando perfectamente.


INT.RAPIDA   NOP   
         BSF      PORTC,2
         CALL   DEMORA406             ;;; RUTINA INTERMITENCIA
         BCF      PORTC,2      ;;;;;   RAPIDA   
         CALL   DEMORA406
            
         GOTO    INT.RAPIDA            

ISR         BSF      PORTA,4    ; ENCIENDO LED DE LA RUTINA
                        ;  DE LA INTERRUPCION
         MOVLW      0x0      ;  CARGA VARIABLES DEMORA
         MOVWF      RET1

DEC22      DECFSZ      RET1    ;  RETARDO DE 769 us
         GOTO      DEC22  






RETORNAR           NOP
         
         BANKSEL   IOCAF
         
         BCF      IOCAF,2      ;  BORRA FLAG
         
         RETFIE

Pero si pongo la demora de 406ms., (no la llamo), se bloquea  en la rutina de ISR.   Asi que me queda ver si por anidar bucles, o por el tiempo como un valor absoluto, si es éste último, descubriré el limite, ya puestos, o ámbos.............


Muchisimas gracias a los dos, SOLUCIONADO. :-/

« Última modificación: 13 de Mayo de 2014, 16:39:04 por JoseLuis2801 »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Problema al retornar de la interrupción (SOLUCIONADO)
« Respuesta #10 en: 13 de Mayo de 2014, 16:48:50 »
Hola,

me alegra poder ayudar.

En cuanto al supuesto bloqueo de la ISR al llamar a la subrutina DEMORA406, creo que lo que está sucediendo no es que se bloquee, es que estás compartiendo las variables que generan la demora, y eso es un problema.
Piensa que cuando se produce la ISR, la posibilidad de que el CPU se encuentre ejecutando la demora de 406mS es altísima, lo que también significa que los valores de RET1, RET2 y RET3 ya fueron establecidos por única vez al ingresar a la subrutina y están decrementandose. Ahora, cuando se produce la ISR, tu vuelves a llamar a DEMORA406, lo que sobreescribe los valores previos de RET1, RET2 y RET3, y no sólo eso, sino que al terminar de ejecutarse, deja las tres variables con valor 0x00, ese 0x00 en las 3 variables, hará que a retornar de la subrutina, el CPU retome desde donde había dejado antes de interrumpir (la demora406) y genere que la demora sea ENORME, debido especialmente al 0x00 de RET3, que requerirá de 256 decrementos antes de poder escapar a la subrutina de demora, siempre y cuando no presiones el pulsador nuevamente, y tenga que volver a contar 256 ciclos largos más.

Espero haber explicado el comportamiento del algoritmo. Si deseas reutilizar la demora fuera y dentro de la ISR, vas a tener que pensar en una solución: una puede ser resguardando manualmente los valores de los registros RET1, RET2 y RET3 al ingresar a la ISR, y restaurarlos antes de salir.

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 JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción (SOLUCIONADO)
« Respuesta #11 en: 13 de Mayo de 2014, 17:48:59 »
Si entendido, y  eso explicaría que saliese a los 55 seg. aprox.

Ok OK, te cojo la idea.  No de esa forma, pero si tengo que utilizar esas demoras de 406ms.

Y el video, para terminar:


En el seg. 19 pulso el microswitch de la placa, luego lo pulso mas veces por si ocurre algo raro, pero va a ser que no.

Q bien verlo funcionar como debe. :P

Bueno otra preguntilla, para que sirve LatC o LatA ? pero un ejemplo practico por favor para que asi yo me entere bien de su utilidad .

Infinitas gracias

 ;-)
« Última modificación: 13 de Mayo de 2014, 17:55:26 por JoseLuis2801 »

Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción (SOLUCIONADO)
« Respuesta #12 en: 15 de Mayo de 2014, 08:00:18 »
BIEN :-/ :-/

He puesto 4 rutinas de 406ms. se van ejecutando sucesivamente, dentro de la ISR, cambiando los nombres a las variables y etiquetas claro. Bueno, las variables solo he definido 3 mas , asi qeu las 4 demoras incluidas, contienen la misma, RET11, RET22, y RET33. 

Y funciona perfecto, no era el valor absoluto del tiempo, sino que se lia al utilizar las mismas como dijistes brunoF.

Es que en mi aplicación, la ISR dura bastante, y como no hay ningún otro recurso que atender, el watchdog lo tengo desactivado.

Bueno, pues ya está todo, infinitas gracias, he aprendido mucho sobre el tema éste de las interrupciones.

Un saludo.


« Última modificación: 15 de Mayo de 2014, 08:08:21 por JoseLuis2801 »

Desconectado JoseLuis2801

  • PIC16
  • ***
  • Mensajes: 168
Re: Problema al retornar de la interrupción (SOLUCIONADO)
« Respuesta #13 en: 16 de Mayo de 2014, 20:04:11 »
Ya por último, he puesto la subrutina de la demora 406ms, fuera de la ISR, y la he ejecutado 14 veces dentro de la ISR, y sin problema alguno, funciona perfectamente.

INT.RAPIDA   NOP   
         BSF      PORTC,2
         CALL   DEMORA406  ;;; RUTINA INTERMITENCIA
         BCF      PORTC,2      ;;;;;   RAPIDA   
         CALL   DEMORA406
            
         GOTO    INT.RAPIDA            

ISR         BSF      PORTA,4    ; ENCIENDO LED DE LA RUTINA
                        ;  DE LA INTERRUPCION
         MOVLW      0x0      ;  CARGA VARIABLES DEMORA
         MOVWF      RET1

DEC222      DECFSZ      RET1    ;  RETARDO DE 769 us
         GOTO      DEC222

         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A

         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         CALL   DEMORA406A
         BCF      PORTA,4      ;; APAGO LED DE LA RUTINA


RETORNAR   NOP
         
         BANKSEL   IOCAF
         
         BCF      IOCAF,2      ;  BORRA FLAG
         
         RETFIE



 

anything