TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: naieto en 05 de Junio de 2006, 14:40:02

Título: Como finalizo una interrupcion antes de tiempo?
Publicado por: naieto en 05 de Junio de 2006, 14:40:02
Hola gente, hay alguna forma de salir abruptamente de una interrupcion antes que esta finalice? ejemplo:
blablalba
#INT_EXT
funcion1()
        {
         for(contador_1=0;contador_1<=10;contador_1++)
            {
             for(contador_2=0;contador_2<=100;contador_2++)
                {
                 for(contador_3=0;contador_3<=200;contador_3++)
                    {
                     if(input(PIN_B1))
                       {
                        TERMINAR CON LA INTERRUPCION
                       }
                     output_high(PIN_A0);
                    }
                 }
             }
          }

main()
      {
       blablabla; 
       while(1)
              {
               enable_interrupts(GLOBAL);
               enable_interrupts(INT_EXT);
               ext_int_edge(L_TO_H);
               output_low(PIN_A0);
               }
       }
Si aprieto un pulsador en rb0 entro en funcion1 y me prende un led hasta que termine la interrupcion (es decir hasta que terminen de contar los for anidados), pero si aprieto un pulsador en rb1 antes que termine dicha interrupcion quiero que esta finalice inmediatamente. Al principio crei que si desabilitaba la interrupcion inmediatamente salia, pero no es asi por las pruebas que hice.
gracias
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: maunix en 05 de Junio de 2006, 14:55:04
Si bien no es una solución elegante... podrias hacerlo.  Has probado con ¿exit? ¿return? ¿goto?

De todas formas, tener rutinas grandes en una rutina de interrupción no es para nada aconsejable y es una mala práctica de programación que debieras comenzar a evitar.  Eso te acarrea mas problemas que soluciones y además no atenderías otra interrupción mientras procesas la actual. 

Saludos




Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: Nocturno en 05 de Junio de 2006, 15:05:10
Puedes utilizar un antiestético goto que te mande al final de la función de interrupción.

P.D.: veo que se me ha adelantado Maunix con la misma solución  :D
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: naieto en 05 de Junio de 2006, 15:23:44
Bueno muchachos, contestaron mas rapido de lo que esperaba. Gracias, voy a probar lo que me sugirieron. Pregunte por las dudas que hubiera alguna funcion especifica de la interrupcion, pero veo que no solo no existe sino que no se usa hacer esto.
Salu2
Sebastian Nieto
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: Sispic en 05 de Junio de 2006, 15:31:01
si , es lo malo que tiene al recrearse en ellas mucho tiempo
Código: [Seleccionar]
#INT_EXT
/************************************************************/
Mi_interrupcion(){
/************************************************************/
 if ((pulsador & 1)== 1){ // segunda pulsacion
    contador_1 = 11;  // lo cual forzara a salir de todos los "for"
    contador_1 = 101;
    contador_1 = 201;
 }
 
 Pulsador ++;
}
/************************************************************/
funcion1(){
/************************************************************/

         for(contador_1=0;contador_1<=10;contador_1++)
            {
             for(contador_2=0;contador_2<=100;contador_2++)
                {
                 for(contador_3=0;contador_3<=200;contador_3++)
                    {

                     output_high(PIN_A0);
                    }
                 }
             }
          }         
         
/************************************************************/
main() {
/************************************************************/     
       blablabla;
     
      byte pulsador;
      Pulsador = 0;
       
       while(1)
              {
               enable_interrupts(GLOBAL);
               enable_interrupts(INT_EXT);
               ext_int_edge(L_TO_H);
               output_low(PIN_A0);
               
               if ((pulsador & 1)== 1){funcion1();} // o verificar la bandera que la produjo
               }
       }

yo usaria banderitas


Este ejemplo quizas no funcione , solo es una idea .

Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: naieto en 05 de Junio de 2006, 15:59:37
Me gusto la idea de hacer
contador_1=11
contador_2=101
contador_3=201
asi me evito usar un goto que recuerdo una vez haberme traido problemas al compilar, no se si a alguien le paso tambien de no poder compilar con goto o fue algun problema mio.
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: Arbolito en 05 de Junio de 2006, 16:05:14
pues si que no es muy estetico el goto no ?
y ademas que se te dijo en el curso sobre los saltos dentro de las interrupciones?
jejeje :lol:
Como andas seba veo que por fin te animaste a postear bueno solo saludarte y darte la vienvenida y
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: naieto en 05 de Junio de 2006, 20:24:01
Bueno, agradezco la ayuda, les cuento que al final puse un if(blablabla) {break;} dentro del lazo for para salir inmediatamente de este y por ende en mi ejemplo salir de la interrupcion. Todo esto venia porque queria hacer un programa que me prenda un led en ra0 si mantenia apretado un pulsador en rb0 un tiempo minimo, si no llegaba a ese tiempo minimo que no haga nada. Aca dejo el programita por si a alguien le interesa:

# INCLUDE <16F84.h>
# USE DELAY(clock=4000000)
# FUSES HS,NOWDT,NOPUT
# USE FAST_IO(A)
# USE FAST_IO(B)

int contador_1;
int contador_2;
int contador_3;
int1 estado_pulsador=0;

#INT_EXT
funcion1()
        {
         estado_pulsador=1;
         for(contador_1=0;contador_1<=5;contador_1++)
            {
             for(contador_2=0;contador_2<=100;contador_2++)
                {
                 for(contador_3=0;contador_3<=200;contador_3++)
                    {
                     if(!input(PIN_B0))
                       {
                        estado_pulsador=0;
                        break;
                       }
                     if(estado_pulsador==1)
                       {output_low(PIN_A0);
                       }
                    }
                 }
             }
          }

main()
   {
    set_tris_a(0);
    set_tris_b(1);
    output_low(PIN_A0);
    while(1)
          {
           enable_interrupts(GLOBAL);
           enable_interrupts(INT_EXT);
           ext_int_edge(L_TO_H);
           if(estado_pulsador==1)
            {
             output_high(PIN_A0);
             delay_ms(2000);
             output_low(PIN_A0);
             estado_pulsador=0;
            }
          }
   }
Cualquier sugerencia para mejorarlo es aceptada por supuesto
salu2 Seba Nieto
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: jfh900 en 05 de Junio de 2006, 20:54:07
Yo pondria:

#define TRUE    1
#define FALSE   0

inicializo la variable Salir = FALSE;

en cada for ponemos (por ejemplo): (contador_1<5) && (!Salir)

Si ponemos Salir=TRUE

Todos los bucles terminan

Un saludo.
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: pikman en 06 de Junio de 2006, 14:14:36
Hola, bueno creo que tambien es posible que en donde quieras finalizar la interrupcion escribas en ASM la instruccion RETFIE, pero cuidado, recuerda que si haces esto deberias recuperar los registros W, STATUS y todo lo que pretendas mantener al ingresar al la interrupcion antes de retornar de ella, esto en C es automatico, bueno dejo la idea, obviamente requiere conocer algo de ASM.

saludos.
Título: Re: Como finalizo una interrupcion antes de tiempo?
Publicado por: maunix en 06 de Junio de 2006, 14:44:32
Hola, bueno creo que tambien es posible que en donde quieras finalizar la interrupcion escribas en ASM la instruccion RETFIE, pero cuidado, recuerda que si haces esto deberias recuperar los registros W, STATUS y todo lo que pretendas mantener al ingresar al la interrupcion antes de retornar de ella, esto en C es automatico, bueno dejo la idea, obviamente requiere conocer algo de ASM.

saludos.

Yo no haría eso.  El C no solo guarda el contexto típico del pic sino que también suele guardar contextos propios del stack interno que utiliza para sus propias variables.

Hacer algo asi, volvería de la rutina de interrupción pero nos podría acarrear otros problemas como sobreescritura de variables por no haberse vaciado correctamente la pila, etc.


Saludos