Autor Tema: NO SE SALE DE LA INTERRUPCION (RETFIE no funciona)  (Leído 2714 veces)

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

Desconectado kurdo22

  • PIC10
  • *
  • Mensajes: 48
NO SE SALE DE LA INTERRUPCION (RETFIE no funciona)
« en: 28 de Octubre de 2004, 06:48:00 »

    Muy buenas, aqui estoy de nuevo a ver si me pueden echar una mano con un problemilla que me ha surgido en una interrupcion. El problema consiste en que en la interrupcion (interrupcion por llegada de dato de la USART2) tengo varios casos en funcion de la informacion obtenida, entoces hace la distincion del caso y ejecuta el caso (call) . Para que se salga le pongo el RETFIE, pero lo ejecuta como un RETURN, es decir, no se sale de la interrupcion al programa principal, sino que vuelve a la siguiente intruccion despues del call.


    Os dejo el codigo lo mas simplificado posible para ver si podeis ehcarle un vistazo y darme alguna solucion.

    Un saludo.

;**************************** EAP Unit Tester ***************************
;
;                         INTETRFACE PC - HARWARE
;
; Descripcion: espero a recibir un telecomando del PC, lo interpreto,
;                     y respondo.
;            
; Tipo Reloj: HS
; Velocidad Reloj: 20MHz
; Reloj Instruccion: 5MHz = 0,2us
; Perro Guardian: deshabilitado
; Proteccion de codigo: OFF
;
;*************************************************************************

;DATOS

   LIST     P=18F8720              ;Tipo de procesador
   INCLUDE <P18F8720.INC>          ;Definicion de registros internos


TXDATO                         equ 0x10 ;Variables VARIAS
RXDATO                         equ 0x11
TEMPORAL                       equ 0x12
CONTADOR                       equ 0x13
CABECERA_PAQUETE_H             equ 0x1B ;Variables TELECOMANDO
CABECERA_PAQUETE_L             equ 0x1C
TELEMETRIA_COMIENZO_H          equ 0x2D ;Variables TELEMETRIA
TELEMETRIA_COMIENZO_L          equ 0x2E
MUSCLE_VOLT_H                  equ 0x2F
MUSCLE_VOLT_L                  equ 0x30
MUSCLE_CURR_H                  equ 0x31
MUSCLE_CURR_L                  equ 0x32
                               
;CODIGO

   ORG   0x00                     ;inicio en el vector de reset
   goto INICIO                    ;va a la primera instrucción de programa
   
            ORG   0x08                     ;vector de interrupción de alta prioridad
   goto CABECERA_TELECOMANDO      ;subrrutina de atención a alta prioridad
   
;------------- SURUTINAS INTERRUPCION
 
;*************************************************************************
;                         RUTINA Recibir un dato
;*************************************************************************

RECIBO   
               
        btfss PIR3,RC2IF               ;testeamos si el buffer de RX lleno(flag RC2IF=1)
        goto  RECIBO                   ;vacio = no hay dato (esperamos)
        movf  RCREG2,W
        movwf RXDATO
        bcf   RCSTA2,CREN              ;limpiamos posibles errores
        bsf   RCSTA2,CREN              ;deshabilitando y habilitando CREN
       
        return

;*************************************************************************   
;                        RUTINA Transmitir un dato
;*************************************************************************

ENVIO        
                       
        movf  TXDATO,W                 ;en el momento en que se pone el dato en TXREG2
        movwf TXREG2                   ;este es enviado

BUCLE

        btfss TXSTA2,TRMT              ;esperamos registro TSR vacio (flag TRMT=1)
        goto  BUCLE                    ;no vacio, esperamos
       
        return
     
;*************************************************************************   
;                RUTINA Escribir Tabla Adquisicion Telecomando
;*************************************************************************

ESCRIBIR_TABLA

        call  RECIBO                   ;dato recibido por puerto serie
        movf  RXDATO,W
        movwf INDF0                    ;guardamos dato recibido en tabla
        incf  FSR0L,1                  ;incrementamos puntero de tabla
     
        return  
 
;*************************************************************************   
;                      RUTINA Leer Tabla Telemetria
;*************************************************************************

LEER_TABLA

        movf  INDF0,W                  ;leemos dato de tabla
        movwf TXDATO
        call  ENVIO                    ;enviamos dato por puerto serie
        incf  FSR0L,1                  ;incrementamos puntero de tabla
     
        return        
     
;*************************************************************************   
;                        RUTINA Enviar Telemetría
;*************************************************************************

TELEMETRIA

        ;Recorrer una tabla en RAM para enviarla
       
        movlw D"6"        ;son 24
        movwf CONTADOR                 ;inicializamos contador de variables de telemetría
       
        movlw H"00"                    ;inicializamos cabecera y final de paquete
        movwf TELEMETRIA_COMIENZO_L
        movlw H"FF"
        movwf TELEMETRIA_COMIENZO_H
       
        movlw TELEMETRIA_COMIENZO_H    ;inicializamos puntero de tabla
        movwf FSR0L
       
BUCLE_ADQUISICION
       
        call  LEER_TABLA
        decfsz CONTADOR,1
        goto  BUCLE_ADQUISICION
       
        return
              
;------------- RUTINA DE ATENCION A INTERRUPCION  
   
CABECERA_TELECOMANDO              
       
       
        bcf   PIE3,RC2IE               ;deshabilitamos interrupción de recepción USART_2
        movf  RCREG2,W
        movwf CABECERA_PAQUETE_H
        bcf   RCSTA2,CREN              ;limpiamos posibles errores
        bsf   RCSTA2,CREN              ;deshabilitando y habilitando CREN

BUCLE_RECIBO
       
        call RECIBO
        movf  RXDATO,W
        movwf CABECERA_PAQUETE_L
                                       
;------------------ INTERPRETACION

INTERPRETAR_TELECOMANDO                ;interpretamos la cabecera de telecomando obtenida

TELECOMANDO_1                          ;1º Comienzo de Conexión

        movlw H"00"                    
        cpfseq CABECERA_PAQUETE_L      ;comparamos y si no es igual saltamos siguiente telecomando
        goto  TELECOMANDO_2
        goto  COMIENZO_CONEXION
       
TELECOMANDO_2                          ;2º Final de Conexión
       
        movlw H"FF"                    
        cpfseq CABECERA_PAQUETE_L      ;comparamos y si no es igual saltamos siguiente telecomando
        goto  TELECOMANDO_3
        goto  FINAL_CONEXION
     
TELECOMANDO_3                          ;3º Señal de Excitación
       
        movlw H"11"                    
        cpfseq CABECERA_PAQUETE_L      ;comparamos y si no es igual saltamos siguiente telecomando
        goto  TELECOMANDO_4
        goto  SENAL_EXCITACION

TELECOMANDO_4                          ;4º Selección de Ganacia
       
        movlw H"22"                    
        cpfseq CABECERA_PAQUETE_L      ;comparamos y si no es igual saltamos siguiente telecomando
        goto  TELECOMANDO_5  
        goto  SELECCION_GANANCIA
       
TELECOMANDO_5                          ;5º Cambio de Estado
       
        movlw H"33"                    
        cpfseq CABECERA_PAQUETE_L      ;comparamos y si no es igual saltamos siguiente telecomando
        goto  TELECOMANDO_6  
        goto  CAMBIO_ESTADO

TELECOMANDO_6                          ;6º Solicitud de Telemetría

        movlw H"44"                    
        cpfseq CABECERA_PAQUETE_L      ;comparamos y si no es igual, error
        goto  SOLICITUD_TELEMETRIA    
        goto  SOLICITUD_TELEMETRIA     ;en caso de ERROR se envia telemetría  
           
;------------------ EJECUCION TELECOMANDO
                     
COMIENZO_CONEXION                      ; 1º

        call  FIN_INTERRUPCION_BAJA_PRIORIDAD
             
;------------------

FINAL_CONEXION                         ; 2º

        call  FIN_INTERRUPCION_BAJA_PRIORIDAD
       
;------------------  
       
SENAL_EXCITACION                       ; 3º

        call  FIN_INTERRUPCION_BAJA_PRIORIDAD
       
;------------------        
       
SELECCION_GANANCIA                     ; 4º

        call  FIN_INTERRUPCION_BAJA_PRIORIDAD
       
;------------------

CAMBIO_ESTADO                          ; 5º
       
        call  FIN_INTERRUPCION_BAJA_PRIORIDAD
       
;------------------        
       
SOLICITUD_TELEMETRIA                   ; 6º
 
        call  FIN_INTERRUPCION_BAJA_PRIORIDAD
           
FIN_INTERRUPCION_BAJA_PRIORIDAD

        bsf   PIE3,RC2IE               ;habilitamos interrupción de recepción USART_2
       
        retfie   

;-------------- SUBRRUTINAS PROGRAMA PRINCIPAL

;*************************************************************************   
;                 RUTINA Inicialización Registros
;*************************************************************************

INICIALIZAR_REGISTROS

        movlw D"2"     ;son 24
        movwf CONTADOR                 ;inicializamos contador de variables de telemetría
       
        movlw TELEMETRIA_COMIENZO_H
        movwf FSR0L                    ;inicializamos puntero de tabla
       
BUCLE_INICIACION
       
        movlw H"68"
        movwf INDF0
        ;clrf INDF0                     ;limpiamos la variable
        incf  FSR0L,1                  ;incrementamos puntero de tabla
        decfsz CONTADOR,1
        goto  BUCLE_INICIACION
       
        return
       
;------------------ oooOOO PROGRAMA PRINCIPAL OOOooo ---------------------
                 
INICIO  
       
;------------------ INICIALIZAMOS INTERRUPCIONES
             
       
        bsf   INTCON,GIE               ;habilitamos interrupciónes
        bsf   INTCON,PEIE              ;habilitamos interrupciónes perifericas
        bsf   PIE3,RC2IE                 ;habilitamos interrupción de recepción USART_2
       
;------------------ INICIALIZAMOS REGISTROS TELEMETRIA
       
        call  INICIALIZAR_REGISTROS    ;limpiamos los registros de telemetría
       
;------------------ INICIALIZAMOS LA USART_2
   
        bsf   TRISG,2                  ;habilitamos RX2 como entrada
        bcf   TRISG,1                  ;habilitamos TX2 como salida
   
        movlw D"129"                   ;9600 baudios
        movwf SPBRG2
       
        movlw B"00000100"              ;8 bits datos, com. asincrona, alta velocidad=(menor error)
        movwf TXSTA2
       
        bsf   RCSTA2,SPEN              ;habilitamos puerto serie (USART2)
       
        bsf   TXSTA2,TXEN              ;habilitamos transmision
        bsf   RCSTA2,CREN              ;habilitamos recepcion

;----------------- BUCLE      
;----------------- FIN DE PROGRAMA PRINCIPAL      

FIN    
       nop
       nop
       nop
       nop
       goto   FIN
       
       END

 

Desconectado kurdo22

  • PIC10
  • *
  • Mensajes: 48
RE: NO SE SALE DE LA INTERRUPCION (RETFIE no funciona)
« Respuesta #1 en: 28 de Octubre de 2004, 09:11:00 »


      Perdonarme pero ya vi el fallo, utilizo call en vez de goto, por eso vuelve despues del retfie.  Ahora lo simulo y me lo hace todo prefectamente PERO NO FUNCIONA, PUEDEN SUGERIRME ALGO ALGO????

     Un saludo

Desconectado escorpion151177

  • PIC12
  • **
  • Mensajes: 61
RE: NO SE SALE DE LA INTERRUPCION (RETFIE no funciona)
« Respuesta #2 en: 28 de Octubre de 2004, 11:13:00 »
hola kurdo22
                      mira, no vi el programa pero queria decirte que tengas en cuenta el tema de la PILA del micro. cuando se hace una llamada CALL o de interrupciones, el micro guarda la ultima direccion que se iba a ejecutar en la pila, para luego de terminar con la subrutina, se carga el contador de programa CP con esa direccion y asi puede seguir ejecutando desde donde habia quedado.
esto de recuperar la direccion previa al pedido de interrupcion o a la peticion de de salto CALL se hace luego de la sentencia  RETURN o RETFIE.

en conclusion : tenes que tener cuidado a la hora de hacer llamadas a subrutinas cuando estas dentro de otra subrutina, porque a la hora de volver con un RETURN o RETFIE,  lo hace a la primera direccion que encuentra en la pila que trabaja en modo LIFO (last input first output, el ultimo que entra es el primero qeu sale), y tal vez esta direccion no corresponda o no sea la qeu vos estabas esperando.

por eso puede ser que cuando reemplazaste CALL  por GOTO  se te soluciono. la instruccion GOTO  es un salto incondicional que no usa la pila para nada.

Desconectado T0ni0

  • PIC16
  • ***
  • Mensajes: 196
RE: NO SE SALE DE LA INTERRUPCION (RETFIE no funciona)
« Respuesta #3 en: 28 de Octubre de 2004, 12:12:00 »
Supongo que habras cambiado todos los call por goto no ?

Por cierto no veo en ninguna parte que limpies el bit de interrupción esa sería una causa segura de no salir de la interrupcion. Bonito PIC yo estoy con el 18F6720 y es una maravilla ya me contarás como va lo de la memória externa y tal?
- T0ni0 -
30RCF112

Desconectado kurdo22

  • PIC10
  • *
  • Mensajes: 48
RE: NO SE SALE DE LA INTERRUPCION (RETFIE no funciona)
« Respuesta #4 en: 28 de Octubre de 2004, 18:02:00 »

   Muchas gracias a todos, dandole vueltas llegue a la misma conclusion del pc, por eso sustitui el call por goto. El programa ya esta funcionando perfectamente, asi que no hace falta que os estrugeis mas los sesos.

   En cuanto al 18f8720 es muy potente, y es increible la multitud de tareas para las que esta preparado. He encontrado una pequeña pega, cuando quiero utilizar la instruccion sleep para ahorrar energia (pasa de 2mA a 2uA) las formas de hacerle salir del sleep son muy limitadas, es mas, solo se puede con eventos externos y muy limitados. Creo que seria mejor que pudiera salir del sleep con cualquier interrupcion. Yo por ejemplo utilizo una comunicacion serie asincrona y me interesa dejarlo en sleep cuando esta en reposo para evitar el consumo e energia y que se despierte cuando lleguen datos, pero no es posible porque solo lo permite con comunicacin serie sincrona, o por lo menos eso dicela data sheet. Otra pega es que ningun timer funciona cuando entra en sleep a excepcion del perro gurardian. Corregirme si me equivoco

     Un saludo y gracias de nuevo