Autor Tema: Saida de interrupción forzada - Overflow de stack  (Leído 1720 veces)

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

Desconectado dragondgold

  • PIC16
  • ***
  • Mensajes: 103
    • Tmax & Gwolf Microcontrollers
Saida de interrupción forzada - Overflow de stack
« en: 13 de Diciembre de 2010, 14:55:57 »
Hola, estoy realizando un frecuencímetro en una pantalla GLCD. Todo funciona perfectamente, la frecuencia medida es precisa y la escritura en el GLCD es correcta. El frecuencímetro es solo una de las funciones que tiene el proyecto. Por lo tanto es tan solo un Sub-Menu del mismo y para salir de la funcion del frecuencimetro debo presionar una tecla para volver al menú anterior. El problema que tenía era que se debía esperar 1 segundo para que se testeara el boton y se realizara la funcion para volver al menú anterior ya que 1 segundo es lo que toma el muestreo de la frecuencia y el metodo usado es preciso pero mantiene al procesador ocupado en eso.
Así que lo mas lógico para que el procesador no deba testear siempre los pulsadores los testeo en una interrupción por flanco sobre la patilla RB0. Hasta aquí todo bien, el problema es, como hago si en la interrupcion detecto que se presiono el pulsador, salir de la interrupcion y a su vez de la funcion del frecuencimetro donde me encontraba antes? Un return; solo me provoca una salida de la interrupción así que use goto_address(); para irme a la dirección de la memoria donde termina la funcion del frecuencimetro y sigue el programa normalmente. Este metodo funciona pero tiene el problema que por consiguiente al no salir como se debe de la interrupción produce un Overflow del stack al entrar y salir varias veces de la interrupción. Mi humilde pregunta y para no se mas extenso, como puedo hacer para evitar este overflow? Hay algun otro metodo que me permita salir de la interrupcion y a su vez de la funcion anterior?

Muchisimas gracias  ;-)

PD: adjunto la parte del programa de la interrupcion y el frecuencimetro.

Código: [Seleccionar]
#INT_EXT                                  //testeo de los pulsadores y su funcion
VOID RB0_ISR (VOID){
      IF(!mux_read(6)){                               //testeo si presiono el boton para volver
         setup_timer_1(T1_DISABLED);                  //si presione el boton desactivo el timer
         BUT_FREC = 0;                    //los botones ya no se usan para el frecuencimetro
         clear_interrupt(INT_EXT);        //habilito otra vez las interrupciones porque el compilador las desactiva aqui para evitar que
         enable_interrupts(INT_EXT);      //entre de nuevo y borro el flag
         enable_interrupts(GLOBAL);
         goto_address(DIR_FIN_FREC);                  //y me voy a la direccion de la memoria donde esta el siguiente paso a la funcion
      }                                  //frec(); de este modo salgo de la misma :D
}

La funcion mux_read(); es una funcion que cree yo que simplemente lo que hace es leer el pin a traves de un multiplexor, funciona correctamente, seria lo mismo a decir IF(!input(PIN_B0))

Este es el código del frecuencimetro

Código: [Seleccionar]
WHILE(1){                                      //bucle infinito
               
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);            //activo el TIMER 1

      WHILE(cycles != 587825){                       //con este bucle demoro 1 segundo                 
   IF(t1_overflow){ t1_overflow = 0; ++OVER; }       //testeo si desborda el TIMER 1
      ++cycles;
   }

reinicio:
setup_timer_1(T1_DISABLED);                            //desactivo el TIMER 1
glcd_text57(0,20,FREQ,2,OFF);                          //borro la frecuencia anterior del GLCD
IF(t1_overflow){ t1_overflow = 0; ++OVER; }            //testeo por ultima vez el desbordamiento del TIMER 1
FRECC = make32(OVER,get_timer1());                     //uno el valor del TIMER y los OVERFLOW en un INT32 para tener la frecuencia
glcd_text57(0,20,FREQ,2,ON);                    //escribo la frecuencia en el GLCD y lo actualizo
glcd_update();
set_timer1(0); OVER = 0; cycles = 0;            //inicializo variables
}
La conclusión final es que sabemos muy poco y sin embargo, es asombroso lo mucho que conocemos. Y más asombroso todavía es que un conocimiento tan pequeño nos pueda dar tanto poder

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Saida de interrupción forzada - Overflow de stack
« Respuesta #1 en: 13 de Diciembre de 2010, 15:34:50 »
  Se me ocurre lo siguiente.... dentro de la interrupción activar una variable usada como flag de tecla.
Y dentro del while del frecuencímetro  evaluar el flag. Claro que deberías descontar ese tiempo que insume el testeo del flag de la cuenta del timer.

  O tal vez evaluar el while así resulte más fácil...

Código: C
  1. WHILE ((cycles != 587825) && (!flag))  // si no paso el segundo y si no fue presionada una tecla
  2. {                       //con este bucle demoro 1 segundo                  
  3.   IF(t1_overflow)
  4.   {
  5.     t1_overflow = 0; ++OVER;
  6.   }       //testeo si desborda el TIMER 1
  7.   ++cycles;
  8. }
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado dragondgold

  • PIC16
  • ***
  • Mensajes: 103
    • Tmax & Gwolf Microcontrollers
Re: Saida de interrupción forzada - Overflow de stack
« Respuesta #2 en: 13 de Diciembre de 2010, 15:47:08 »
Si es lo que habia pensado en un principio, no hay alguna forma de borrar el stack digamos como si se saliera de la interrupcion para no provocar ese overflow??

Bueno no existe otra solucion lo que pido es mucho jaja así que opte por la opcion de los flag y modifique los tiempos y funciona de 10 muchas gracias!!!  :mrgreen:
« Última modificación: 13 de Diciembre de 2010, 16:26:31 por dragondgold »
La conclusión final es que sabemos muy poco y sin embargo, es asombroso lo mucho que conocemos. Y más asombroso todavía es que un conocimiento tan pequeño nos pueda dar tanto poder

Desconectado Tisco

  • PIC16
  • ***
  • Mensajes: 108
Re: Saida de interrupción forzada - Overflow de stack
« Respuesta #3 en: 13 de Diciembre de 2010, 17:09:23 »
buenas!
Si el microcontrolador que usas es un pic18 puedes usar la instruccion POP de ensamblador. Con ella decrementas el stack pointer en 1. despues de hacer el pop puedes hacer el goto. Esto es valido si entre el POP y el GOTO no puede suceder nada que interrumpa la ejecucion lineal del codigo.

un saludo!


 

anything