Autor Tema: Problema con interrupción del puerto serie. [Solucionado]  (Leído 3387 veces)

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

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Problema con interrupción del puerto serie. [Solucionado]
« en: 08 de Mayo de 2011, 19:12:12 »
Buenas a todos,

tengo un problemilla con un código que estoy haciendo... el programa lee un valor del ADC y lo envía al puerto serie y a un LCD, y a su vez, cuando recibe algo por el puerto serie, se ejecuta la interrupción del puerto serie, lee el valor y lo muestra por el LCD.

pues resulta que todo funciona bien hasta que le envío un carácter por el puerto serie, que se queda colgado al entrar en la interrución...    :5] :5] :5]

este es el código, a ver si alguien me puede echar una mano y ve algún fallo


//Incluimos la libretia del PIC
#include "16F877A.h"

#device adc=10
//Configuramos el reloj a 4MHz
#use delay(clock=4000000)
#include "lcd.c"
//Configuramos los parámetros del puerto RS-232
#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7)//,enable=PIN_D5)

#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08

//Configuramos los fuses adecuados
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,BROWNOUT

#define PULSADOR pin_b6

int keypress=0, dato=0;

void borrar_lcd()
{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"                ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"                ");
   lcd_gotoxy(1,1);
}

//directiva para interrupción del puerto serie
#int_rda
void rda_isr()
{
   dato=1;
}
void config(void)
{
   enable_interrupts(INT_RDA); //indicamos que queremos usar la int del serial
   enable_interrupts(GLOBAL); //habilitamos las interrupciones
}

//Programa principal
void main(void)
{
   int16 valor=0;
   float result=0;
   set_tris_b(0b01111111); //Configuramos el puerto B de entrada de B0-B6
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);

   config();
   lcd_init();
   borrar_lcd();
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Tension=");
  
   while(TRUE)
   {
      valor=read_adc();
      result=(valor/168.4);
      lcd_gotoxy(9,1);
      printf(lcd_putc,"%2.2fv \n",result);
      delay_ms(100);
      printf("%2.2f v \n\r"result);
      if(dato==1)
      {
         keypress=getc();
         lcd_gotoxy(1,2);
         printf(lcd_putc,"%u",keypress);
         dato=0;
      }
   }
}


supongo que no debo estar configurando bien la interrupción, pero yo no veo el fallo...
espero haberme explicado,

un saludo y gracias...
« Última modificación: 11 de Mayo de 2011, 08:10:51 por wannaky »

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Re: Problema con interrupción del puerto serie.
« Respuesta #1 en: 08 de Mayo de 2011, 19:14:26 »
otra cosa, utilizo un programilla que se llama "ComPort Library example" para monitorizar el puerto COM (lo adjunto aquí...)  lo comento por si pudiese ser problema del programa este...

gracias
« Última modificación: 08 de Mayo de 2011, 19:17:29 por wannaky »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Problema con interrupción del puerto serie.
« Respuesta #2 en: 08 de Mayo de 2011, 19:27:58 »
una idea:

cuando dato==1 haz disabled_interrupts(int_rda) y antes de salir del condicional, haz enabled_interrups(int_rda)
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Re: Problema con interrupción del puerto serie.
« Respuesta #3 en: 09 de Mayo de 2011, 07:25:13 »
una idea:

cuando dato==1 haz disabled_interrupts(int_rda) y antes de salir del condicional, haz enabled_interrups(int_rda)

Hola PalitroqueZ, he probado lo que me has comentado y nada de nada...

Código: [Seleccionar]
#int_rda
void rda_isr()
{
   disable_interrupts(GLOBAL);
   dato=1;
   printf(lcd_putc,"P");
   enable_interrupts(GLOBAL);
}
también he hecho que envíe una 'P' al LCD para ver si entra o no entra a la interrupción, y he visto que si, pero me llena el LCD de PPPPPPPPPPPPPPPPPPPPPPP, como si al entrar la primera vez se quedase colgado y entrando siempre...

alguien tiene idea de que puede ser?!?!?!  :huh: :huh: :huh:

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupción del puerto serie.
« Respuesta #4 en: 09 de Mayo de 2011, 10:02:02 »
  Creo que Palitroquez se refiere al "if (dato == 1)" que tenés en el bucle principal, y no a la rutina de interrupción
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Re: Problema con interrupción del puerto serie.
« Respuesta #5 en: 09 de Mayo de 2011, 10:38:36 »
aaaahhh... vale vale... jejeje... :z) :z) :z)   esta tarde cuando llegué lo probaré, a ver que tal

gracias...

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Re: Problema con interrupción del puerto serie.
« Respuesta #6 en: 09 de Mayo de 2011, 11:03:33 »
una idea:

cuando dato==1 haz disabled_interrupts(int_rda) y antes de salir del condicional, haz enabled_interrups(int_rda)

pero no entiendo porqué tendría que funcionar así?!?!?!  no le veo la lógica :shock: :shock: :shock: :shock:  pero lo probaré, que no pierdo nada y ya os comentaré...

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupción del puerto serie.
« Respuesta #7 en: 09 de Mayo de 2011, 11:06:00 »
  Es para evitar que haya otra llamada a la interrupción, mientras estás escribiendo el dato en el LCD.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Problema con interrupción del puerto serie.
« Respuesta #8 en: 09 de Mayo de 2011, 12:25:36 »
si es como dice Angelgris,

pues si que esta raro wannaky, entonces intenta enviar y recibir solo datos y no utilices la lcd a ver como va
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado Tisco

  • PIC16
  • ***
  • Mensajes: 108
Re: Problema con interrupción del puerto serie.
« Respuesta #9 en: 09 de Mayo de 2011, 15:10:56 »
Hola,
yo no he usado nunca CCS, pero no veo que borres el flag de interrupcion de recepcion del puerto serie (a no ser que lo haga automaticamente el compilador al entrar en la rutina de interrupcion) Si no borras el flag, es normal que este a entrar y salir seguido de la misma. Supongo que si usas getc(); en la propia rutina de interrupcion ya te borrara el flag (habria que ver como funciona en ese compilador exactamente), si no hazlo de forma manual.
un saludo!

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Re: Problema con interrupción del puerto serie.
« Respuesta #10 en: 10 de Mayo de 2011, 11:10:10 »
Buenas,

he probado de deshabilitar al entrar en el if(dato==1) i habilitar al salir y me continua fallando... yo creo que ha de ser problema de lo que comenta Tisco, que no le digo al pic mediante un flag que la interrupción ya se ha procesado, y por eso se queda continuamente ejecutando el código que hay en la interrupción.

Alguien sabe que bit es el que he de setear para indicarle al pic que ya se ha ejecutado el código de la interrupción y de esta forma solo se haga una vez.
programa en CCS

gracias y un saludo...

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Problema con interrupción del puerto serie.
« Respuesta #11 en: 10 de Mayo de 2011, 13:29:59 »
Probaste sacar de la interrupción la escritura del LCD? Postea el código de la interrupción Para ver como quedó.
Saludos.
              Jukinch
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado Tisco

  • PIC16
  • ***
  • Mensajes: 108
Re: Problema con interrupción del puerto serie.
« Respuesta #12 en: 10 de Mayo de 2011, 14:48:11 »
Hola de nuevo,
el bit que te indica que hay un nuevo dato en el buffer de recepcion se setea automaticamente por hardware, tu lo que tienes es que resetearlo por software.
En el 16F877A dicho bit es el RCIF del registro PIR1.
De todas formas estaria bien que pusieses el codigo como dice Jukinch para ver que estas haciendo.
un saludo!

Desconectado wannaky

  • PIC12
  • **
  • Mensajes: 92
Re: Problema con interrupción del puerto serie.
« Respuesta #13 en: 10 de Mayo de 2011, 16:05:35 »
Buenas, este es el código que he probado ahora mismo...
Código: [Seleccionar]
//Incluimos la libretia del PIC
#include "16F877.h"

#device adc=10
//Configuramos el reloj a 4MHz
#use delay(clock=4000000)
#include "lcd.c"
//Configuramos los parámetros del puerto RS-232
#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7)//,enable=PIN_D5)

#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08

//Configuramos los fuses adecuados
#fuses NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG

char keypress=0;
int dato=0;

void borrar_lcd()
{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"                ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"                ");
   lcd_gotoxy(1,1);
}

//directiva para interrupción del puerto serie
#int_rda
void rda_isr()
{
   dato=1;
   keypress=getc();
   printf(lcd_putc,"%c",keypress);
}
void config(void)
{
   enable_interrupts(GLOBAL); //habilitamos las interrupciones
   enable_interrupts(INT_RDA); //indicamos que queremos usar la int del serial
}

//Programa principal
void main(void)
{
   int16 valor=0;
   float result=0;
   set_tris_b(0b01111111); //Configuramos el puerto B de entrada de B0-B6
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);

   config();
   lcd_init();
   borrar_lcd();
   printf(lcd_putc,"Tension=");
   
   while(TRUE)
   {
      valor=read_adc();
      result=(valor/168.4);
      lcd_gotoxy(9,1);
      printf(lcd_putc,"%2.2fv \n",result);
      delay_ms(100);
      printf("%2.2f v \n\r"result);
      if(dato==1)
      {
         dato=0;
      }
   }
}


La cuestión es que así funciona y de esta otra manera no --->  :5] :5] :5] :5]

Código: [Seleccionar]
#include "16F877.h"

#device adc=10
//Configuramos el reloj a 4MHz
#use delay(clock=4000000)
#include "lcd.c"
//Configuramos los parámetros del puerto RS-232
#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7)//,enable=PIN_D5)

#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08

//Configuramos los fuses adecuados
#fuses NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG

//#define PULSADOR pin_b6

char keypress=0;
int dato=0;

void borrar_lcd()
{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"                ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"                ");
   lcd_gotoxy(1,1);
}

//directiva para interrupción del puerto serie
#int_rda
void rda_isr()
{
   dato=1;
}
void config(void)
{
   enable_interrupts(GLOBAL); //habilitamos las interrupciones
   enable_interrupts(INT_RDA); //indicamos que queremos usar la int del serial
}

//Programa principal
void main(void)
{
   int16 valor=0;
   float result=0;
   set_tris_b(0b01111111); //Configuramos el puerto B de entrada de B0-B6
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);

   config();
   lcd_init();
   printf(lcd_putc,"Tension=");
   
   while(TRUE)
   {
      valor=read_adc();
      result=(valor/168.4);
      lcd_gotoxy(9,1);
      printf(lcd_putc,"%2.2fv \n",result);
      delay_ms(100);
      printf("%2.2f v \n\r"result);
      if(dato==1)
      {
         keypress=getc();
         lcd_gotoxy(1,2);
         printf(lcd_putc,"%c",keypress);
         dato=0;
      }
   }
}

Lo único que he hecho ha sido en lugar de leer el carácter enviado por el serie desde el main, lo he leído directamente en la interrupción, pero así no me gusta, porque quiero ejecutar el mínimo código posible dentro de la interrupción, quiero que todo se ejecute en el main...

pero no se comoooooooooooo!!!!!!!!! :? :? :? :? :? :? :? :?

Tisco, como trabajo en CCS sobre ese bit o ese registro?!?!?! en ASM si que lo he hecho, pero en CCS no se como... sabes de algún manual?!?!!?!

gracias, y nos vemos... ;-) ;-) ;-)

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupción del puerto serie.
« Respuesta #14 en: 10 de Mayo de 2011, 19:45:59 »
  Es que si no lees el dato dentro de la rutina de interrupción no se te va a borrar el flag de la misma y por lo tanto vas a estar reentrando constantemente.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas