Autor Tema: problema con interrupcion  (Leído 4019 veces)

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

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
problema con interrupcion
« en: 05 de Mayo de 2008, 12:38:41 »
HOLA micromanos!!! He realizado un pequeño programa con la finalidad de poco a poco ir ilando un menu, utilizando la interrupcion externa (RB0) de un 18f2520. Lo compilo en CCS y si me entra en la interrupcion pero los mensajes en el LCD salen fuera de lugar.
¿De qué manera afecta la interrupcion al LCD?
Os lo mando, aber que opinais:

#include <18F2520.h>

#fuses WDT1024, XT, NOPROTECT, BROWNOUT, BORV45, NOPUT, NOCPD
#fuses NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN
#fuses NOWRTC, NOWRTB, NOEBTR, NOEBTRB, NOCPB, NOLPT1OSC, MCLR, NOXINST

#use delay(clock=4000000)

#byte pb       =0xF81
#bit t_ok      =pb.0      // RB0
#bit t_mas       =pb.1      // RB1
#bit t_mns       =pb.2      // RB2
 
#byte intcon   =0xFF2
#bit  intf     =intcon.1
//#byte intcon3   =0xFF0
//#bit  intf1    =intcon3.0


#include <lcdult.h>

void main()
{
   port_b_pullups(true);
   setup_adc_ports(NO_ANALOGS);

   setup_wdt(WDT_ON);
   intf=0;
   enable_interrupts(INT_EXT);
   ext_int_edge(h_to_l);
   enable_interrupts(GLOBAL);
   lcd_init();
   delay_ms(100);
   
   while(true)
   {
      restart_wdt();

      lcd_gotoxy(1,1);
      lcd_putc("Menu");
      delay_ms(1000);
   }
}
#INT_EXT
menu()
{
   disable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT);
   delay_ms(300);
   lcd_putc("\f");
   delay_ms(100);
   lcd_gotoxy(1,1);
   lcd_putc("Linea1");
   lcd_gotoxy(1,2);
   lcd_putc("Linea2");
   lcd_gotoxy(1,3);
   lcd_putc("Linea3");
   lcd_gotoxy(1,4);
   lcd_putc("Linea4");
   delay_ms(2000);
   intf=0;
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   }


Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema con interrupcion
« Respuesta #1 en: 05 de Mayo de 2008, 14:09:56 »
Hola.

Tengo los siguientes comentarios:

1) Es mejor utilizar flags en la interrupcion para ser procesados en el main, podrias colocar el flag menu_ok=true en la interrupcion por ejemplo, y hacer toda la rutina de muestra del menu en el programa principal.

2) A mi nunca me ha afectado el uso de las interrupciones a la LCD (me imagino que la libreria que usas para el manejo de la LCD usa un puerto diferente al B cierto??  :) )

3) Que yo sepa, no es necesario limpiar la bandera de la interrupcion (CCS lo hace por uno!!!  :mrgreen: ), pero eso ya es opcional.

4) Yo siempre configuro el ext_int_edge, antes de habilitar la interrupcion (la verdad no se si eso afecte en algo, lo hago porque se ve mas ordenado).

5) No entiendo bien a lo que dices "mensajes fuera de lugar" ... te refieres a que no salen en la posicion en la que programaste? (Por cierto, lcd_putc('\f'), ya tiene incluido el lcd_gotoxy(1,1))

Espero te sirvan.

Saludos y muchos exitos
El papel lo aguanta todo

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: problema con interrupcion
« Respuesta #2 en: 05 de Mayo de 2008, 14:27:38 »
Gracias por responder MLO.

Si me refiero a que no salen los mensajes en la direccion especificada.

En tu punto 1) te refieres a que en el bucle infinito while1 esté testeando una variable para entrar en la interrupcion.

Un saludo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: problema con interrupcion
« Respuesta #3 en: 05 de Mayo de 2008, 14:38:13 »
¿Y si no activas la interrupción el LCD se porta correctamente?

A ver si va a ser un LCD de colores no apto para daltónicos  :D
(Disculpa el exceso de confianza, pero no podía evitar hacer la broma)

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema con interrupcion
« Respuesta #4 en: 05 de Mayo de 2008, 15:05:02 »
 :D :D :D :D :D :D :D Ah, Nocturno, la broma estubo buena (a costas del amigo daltonico82)

Mira, daltonico82 (oye, curioso nombre!!) en el main (dentro del while(true)) puede haber un if(menu_ok){...} en donde, ademas de inicializar el flag, colocas la parte del codigo de mostrar el menu en la LCD y listo. En este caso la interrupcion solo se encargaria de volver a asignar el valor del flag menu_ok a "true". Ahora, si necesitas que lo haga siempre (por si hay que escoger otras cosas mas, como "up" o "down" dentro del menu principal), entonces lo puedes colocar dentro de un while y quedara mejor. Todo depende de lo que vallas ha hacer despues con el menu cierto?

Saludos
El papel lo aguanta todo

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: problema con interrupcion
« Respuesta #5 en: 05 de Mayo de 2008, 15:35:39 »
 :D :D :D...Eureka!!!!!

Ah Nocturno!!! no me importa la confianza!!! la verdad me estaba volviendo daltonico el tema!!!!.

Ha funcionado con el truco de MLO pero no entiendo muy bien porque ya ke funcionalmente tendria que funcionar igual.

Sabia que de la rutina del LCD (con puerto C)no podia ser ya que funciona a las mil maravillas.

Por ahora va asi el tema:

#include <18F2520.h>

#fuses WDT1024, XT, NOPROTECT, BROWNOUT, BORV45, NOPUT, NOCPD
#fuses NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN
#fuses NOWRTC, NOWRTB, NOEBTR, NOEBTRB, NOCPB, NOLPT1OSC, MCLR, NOXINST

#use delay(clock=4000000)

#byte pb       =0xF81
#bit t_ok      =pb.0      // RB0
#bit t_mas       =pb.1      // RB1
#bit t_mns       =pb.2      // RB2
 
#byte intcon   =0xFF2
#bit  intf     =intcon.1
//#byte intcon3   =0xFF0
//#bit  intf1    =intcon3.0
int ok;

#include <lcdult.h>

void main()
{
   ok=0;
   port_b_pullups(true);
   setup_adc_ports(NO_ANALOGS);

   setup_wdt(WDT_ON);
   intf=0;
   set_tris_b(0b00000001);
    ext_int_edge(h_to_l);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   lcd_init();
   delay_ms(100);
   
   while(true)
   {
      restart_wdt();

      lcd_gotoxy(1,1);
      lcd_putc("Menu");
      delay_ms(1000);
      if(ok==1)
      {
      lcd_putc("\f");
   delay_ms(100);
   lcd_gotoxy(1,1);
   lcd_putc("Linea1");
   lcd_gotoxy(1,2);
   lcd_putc("Linea2");
   lcd_gotoxy(1,3);
   lcd_putc("Linea3");
   lcd_gotoxy(1,4);
   lcd_putc("Linea4");
   delay_ms(2000);
      }
     
   }
}
#INT_EXT
menu()
{
   ok=1;
   disable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT);
   
   intf=0;
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   }


Por cierto sabeis si es necesario especificar el pin asociado a la interrupcion como entrada -->> //set_tris_b(0b00000001);


Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema con interrupcion
« Respuesta #6 en: 05 de Mayo de 2008, 15:53:46 »
Hola ... que bueno que te funcionara....

Pues, yo nunca lo hago (al hecho de asociar el pin de salida en el puerto, has la prueba comentando el set_tris_b) y me funciona bien.

Yo lo que haria ahora es quitar la parte del codigo en la interrupcion.
Código: [Seleccionar]
#INT_EXT
void menu(void)
{
   ok=1;
   disable_interrupts(GLOBAL);//quitaria esta parte
   disable_interrupts(INT_EXT);//y esta parte
   
   intf=0;// y esta parte
   enable_interrupts(GLOBAL);// y esta
   enable_interrupts(INT_EXT);//y esta
   }

y la variable ok, podria ser del tipo int1, para ahorrar memoria (como solo toma dos valores true o false ). Lo del bit intf yo lo quitaria tambien, por lo que te dije que el CCS limpia las benderas despues de la interrupcion, pero sirve para hacerle seguimiento al programa el el debugger.

Por lo general, las banderas de interrupcion las coloco como variables globales (las defino antes del void main (void)).

Saludos
El papel lo aguanta todo

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: problema con interrupcion
« Respuesta #7 en: 06 de Mayo de 2008, 13:16:54 »
Hola amigos; gracias a los consejos que me habeis dado por fin he concluido un pequeño programa que consta de un menu con tres teclas:
-tecla ok(tok)
-tecla incremento(tmas)
-tecla decremento(tmns)
 Una vez elegida la opción se vuelve al menu de inicio trancurrido un tiempo o pulsando tok.
Buenos os lo dejo, aunque sigo planteandome una pregunta:

¿Por qué funciona mal el LCD (los mensajes no salen en la posicion xy especificada) cuando coloco el código que va despues de IF(ENTRAMENU=1) lo coloco en la rutina de atencion a la interrupcion externa?


#include <18F2520.h>

#fuses NOWDT, XT, NOPROTECT, BROWNOUT, BORV45, NOPUT, NOCPD
#fuses NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN
#fuses NOWRTC, NOWRTB, NOEBTR, NOEBTRB, NOCPB, NOLPT1OSC, MCLR, NOXINST

#use delay(clock=4000000)

#byte pb       =0xF81
#bit t_ok      =pb.0      // RB0
#bit t_mas       =pb.1      // RB1
#bit t_mns       =pb.2      // RB2

#byte intcon   =0xFF2
#bit  intf     =intcon.1
//#byte intcon3   =0xFF0
//#bit  intf1    =intcon3.0
#include <lcdult.h>

int1 entramenu;
static unsigned int8 test, i, tok, tmas, tmns;


void main()
{
   entramenu=0;
   i=0;
   test=0;
   port_b_pullups(true);
   setup_adc_ports(NO_ANALOGS);
   intf=0;
   set_tris_b(0b00000111);
   ext_int_edge(h_to_l);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   lcd_init();
   delay_ms(100);

   while(true)
   {
      lcd_gotoxy(1,1);
      lcd_putc("Menu");
      delay_ms(1000);
      if(entramenu==1)
      {

 disable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT);
   delay_ms(300);
   lcd_putc("\f");
   lcd_gotoxy(1,1);
   lcd_putc("Opcion1");
   delay_ms(30);
   lcd_gotoxy(1,2);
   lcd_putc("Opcion2");
   delay_ms(30),
   lcd_gotoxy(1,3);
   lcd_putc("Opcion3 ");
   delay_ms(30);
   lcd_gotoxy(1,4);
   lcd_putc("OPCION:");



   for(i=0;i!=255;i++)     // 5 segundos para pulsar alguna tecla
   {
      delay_ms(20);
      lcd_gotoxy(8,4);
      printf(lcd_putc,"%u",test);
      if (!t_ok){delay_ms(300); break;}
      else if (!t_mas){i=0; delay_ms(300); test++; if(test>3){test=0;};}
      else if (!t_mns){i=0; delay_ms(300); test--; if(test==255){test=3;};}
   };


   if(test==0)
   {
      intf=0;
      enable_interrupts(GLOBAL);
      enable_interrupts(INT_EXT);
      lcd_putc("\f");

   }

  else if(test==1){
   lcd_putc("\f");
   lcd_gotoxy(1,1);
   lcd_putc("Opcion1 Seleccionada");

   delay_ms(2000);

   intf=0;
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   test=0;
  }

  else if(test==2){
  lcd_putc("\f");
   lcd_gotoxy(1,1);
   lcd_putc("Opcion2 Seleccionada");

   delay_ms(2000);

   intf=0;
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   test=0;
}

  else if(test==3){
  lcd_putc("\f");
   lcd_gotoxy(1,1);
   lcd_putc("Opcion3 Seleccionada");

   delay_ms(2000);

   intf=0;
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   test=0;
  }
 entramenu=0;
 lcd_putc("\f");
}
}
}

#INT_EXT
menu()
{
   entramenu=1;
}


Desconectado Gonzalo_BlackHawk

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 519
Re: problema con interrupcion
« Respuesta #8 en: 06 de Mayo de 2008, 14:01:02 »
Este es otro ejemplo clarisimo de porque hay que mantener el código en las interrupciones lo mas corto posible. Yo creo fielmente que los delay y los int no se llevan bien (sobretodo si el delay es de 2 segundos :D).

Un saludo.
"Siempre piensa si el jugo vale la exprimida..."

"La muerte esta tan segura de vencer que nos da toda una vida de ventaja."

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: problema con interrupcion
« Respuesta #9 en: 06 de Mayo de 2008, 16:20:57 »
 :-/ :mrgreen:YA pero no he visto por ninguna parte (datasheet) que no pueda mostrar mensajes en el LCD(partiendo de una libreria muy fiable) en el seno de una rutina de atención a la interrupción... Aunque el código sea corto (un "hola mundo") si lo coloco dentro de la rutina sale en una posición equivoca.

Sigo preguntandome el por qué.¿De qué carece o que le sobra al código?

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema con interrupcion
« Respuesta #10 en: 06 de Mayo de 2008, 16:43:28 »
Hola.

Oye, y por que no pruebas en eviar solo una letra a una posicion especifica a ver que sucede???? Para ir "desenmaranando" :o el problemilla

Saludos
El papel lo aguanta todo


 

anything