Autor Tema: Comunicacion RS232... el micro se queda colgado....  (Leído 4361 veces)

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

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Comunicacion RS232... el micro se queda colgado....
« en: 07 de Septiembre de 2005, 13:00:00 »
Hola nuevamente a todos, hoy toca RS232, bueno el tema es que he realizado un pequeño programita en RS232 y no se porque se me queda colgado antes de iniciar el while (true), he estado leyendo lo del stream del 232 pero ni por asomo consigo que  esto funcione, ni debugeandolo ni nada, alguien me puede dar una idea? utilizo la interrupcion RDA para recoger los caracteres aki dejo el programa:

#include <16f876a.h>
#include <stdlib.h>
#include <string.h>
#fuses HS,NOWDT,NOLVP,NOBROWNOUT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7,RESTART_WDT)

char recepcion[8];
short int activado=0;
// funcion de espera
void wait (int y)
{
int i,x;
   for (x=0;x<y;x++)
      for (i=0;i<y;i++);
}
// INTERRUPCION DE LA UART POR RX
#int_RDA
void RDA_isr()
{
int i;
disable_interrupts(INT_RDA);
for (i=0;i<16;i++)
   recepcion=NULL;
//recibimos comando
gets(recepcion);
//hacemos ECO
printf(recepcion);
if (recepcion[0] == "R")
   {
   activado=~activado;   
   }
if (activado == 1)
   {
   printf("Alarma activada!!!!"Giño;
   putc(0x0d);
   }
else
   {
   printf("Alarma desactivada!!!!"Giño;
   putc(0x0d);
   }
enable_interrupts(INT_RDA);
}

void main (void)
{
int i;
set_tris_a(0); // todo el puerto a salida
set_tris_c(0x80);// todo el puerto c salida menos C7 que es rx de rs232
enable_interrupts(INT_RDA);         //Se habilita la interrupción por recepción de datos por el pin RX
enable_interrupts(GLOBAL);
output_bit(pin_a5,1);
printf("Inicializando sistema...."Giño;
printf("%C",0x0d);
delay_ms(100);
while (1)
   {
      printf("Esperando activacion!!!"Giño;
      putc(0x0d);   
      while (activado==1) //alarma activada
      {
      output_bit(pin_a5,1);
      delay_ms(500);
      output_bit(pin_a5,0);
      delay_ms(500);
      while (!input(pin_b7)&&activado) //si la alarma esta activa y el interruptor tambien salta!
         {
         output_bit(pin_a5,1);
         printf("ATD123456789;"Giño;
         putc(0x0d);
         delay_ms(30000);
         printf("ATH"Giño;
         putc(0x0d);
         delay_ms(5000);
         }   
      }
   }

}


Gracias, y haber si alguien me saca del problema porque llevo toda la tarde con lo mismo, y no logro hacerlo funcionar ni de coña......
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #1 en: 07 de Septiembre de 2005, 13:30:00 »
Hola xerex, mirando el código asi por encima creo que el problema lo puedes tener en el bucle for que tienes dentro de la rutina de servicio de la interrupcion del puerto serie, pq si no lees siempre 16 caracteres el bucle no puede terminar con lo que el pic se quedara pillado ahi esperando que le envies los 16 caracteres. El hecho de que te ocurra antes de entrar en el bucle while(1), puede ser que despues de un reset la usart del micro lea algun byte de basura con lo cual se activa la interrupción y ya se te queda pillado el micro esperando que le metas los 16 caracteres.

Prueba a quitar el bucle y leer solo un caracter, a ver si te funciona.

Un saludo.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #2 en: 07 de Septiembre de 2005, 14:06:00 »
bueno pues no creo que sea eso omix, gracias por contestar, he modificado el codigo como lo tenia hasta que he empezado a tener problemas con el, por lo que he visto se queda en loop infinito en algun sitio, pero si atiende a las interrupciones 232 ya que cuando envio datos al pic, este me hace eco y lo estoy monitoreando por el hyperterminal, y no hay datos ni nada extraño de mas, aqui te dejo el programa, se queda al iniciar el while (true) y de hay no lo mueves....

#include <16f876a.h>
#include <stdlib.h>
#include <string.h>
#fuses HS,NOWDT,NOLVP,NOBROWNOUT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)

char recepcion;
short int activado=0;
// funcion de espera
void wait (long int y)
{
long int i,x;
   for (x=0;x<y;x++)
      for (i=0;i<y;i++);
}
// INTERRUPCION DE LA UART POR RX
#int_RDA
void RDA_isr()
{
int i;
/*disable_interrupts(INT_RDA);*/
//recibimos comando
gets(recepcion);
//hacemos ECO
printf(recepcion);
if (recepcion == "R")
   {
   if (activado == 0)
      activado = 1;
   else
      activado = 0;
   }
}

void main (void)
{
int i;
activado=0;
set_tris_a(0); // todo el puerto a salida
set_tris_c(0x80);// todo el puerto c salida menos C7 que es rx de rs232
enable_interrupts(INT_RDA);         //Se habilita la interrupción por recepción de datos por el pin RX
enable_interrupts(GLOBAL);
while (1)
   {
      output_bit(pin_a5,0); <- se debe de quedar por aki....
      wait (60000);
      wait (60000);
      wait (60000);
      output_bit (pin_a5,1);
      wait (60000);
      wait (60000);
      wait (60000);
      while (!input(pin_b7)&&activado) //si la alarma esta activa y el interruptor tambien salta!
         {
         output_bit(pin_a5,1);
         printf("ATD123456789;"Giño;
         putc(0x0d);
         delay_ms(30000);
         printf("ATH"Giño;
         putc(0x0d);
         delay_ms(5000);
         }   
   }

}

que desastre....... haber si me iluminas!!! jeje gracias.

Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #3 en: 07 de Septiembre de 2005, 14:44:00 »
Lo que recibes no puedes enviarlo inmediatamente, porque obligas al programa a perder los bytes recibidos o empieza a retrasar mucho, por eso se cuelga....
A mi me paso lo mismo y no entendia porque, hasta que vi que guardando lo recibido en un buffer (un array de la longitud que necesitas) si andaba bien....
Pruebalo, hay ejemplos en el mismo CCS de como hacerlo, buscalos en los ejemplos, en este momento no recuerdo los nombres de los archivos....Sonrisa GigantePayasoPayaso
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #4 en: 07 de Septiembre de 2005, 16:15:00 »
Esto no me lo creo.... mira lo que he cambiado el while (true) por un for(;Giño

y ha funcionado hasta el momento.... porque? dejo el codigo para que le echeis un vistazo.
#include <16f876a.h>
#include <stdio.h>
#include <string.h>
#fuses HS,NOWDT,NOLVP,NOBROWNOUT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)

char recepcion;
short int activado=0;
// funcion de espera
void wait (long int y)
{
long int i,x;
   for (x=0;x<y;x++)
      for (i=0;i<y;i++);
}
// INTERRUPCION DE LA UART POR RX
#int_RDA
void RDA_isr()
{
//recibimos comando
recepcion=getc();
//hac0emos ECO
printf(recepcion);
if (recepcion == "R")
   {
   if (activado == 0)
      activado = 1;
   else
      activado = 0;
   }
}

void main (void)
{

activado=0;
set_tris_a(0); // todo el puerto a salida
set_tris_c(0x80);// todo el puerto c salida menos C7 que es rx de rs232
output_bit (pin_a5,1);
enable_interrupts(INT_RDA);         //Se habilita la interrupción por recepción de datos por el pin RX
enable_interrupts(GLOBAL);
for(;Giño
   {
   output_bit(pin_a5,1);
   delay_ms (500);   
   output_bit (pin_a5,0);
   delay_ms (500);
      
      while ((input(pin_b7)==0)&&(activado==1)) //si la alarma esta activa y el interruptor tambien salta!
         {
         output_bit(pin_a5,1);
         printf("ATD123456789;"Giño;
         putc(0x0d);
         delay_ms(30000);
         printf("ATH"Giño;
         putc(0x0d);
         delay_ms(5000);
         }   
   }

}

voy a seguir trasteando.... Gracias a todos
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #5 en: 07 de Septiembre de 2005, 18:35:00 »
Bueno he seguido trasteando y he conseguido que funcione a medias lo que quiero hacer, pero ahora pasa una vez por la interrupcion y la segunda vez no pasa por tanto es como si ya no la hiciera caso... porque???? he probado a eliminar el error de overrrun pero no parece que funcione:
dejo el codigo por si alguien tiene alguna idea de porque no accede a la segunda vez que le llega el comando a la interrupcion:

#include <16f876a.h>
#include <stdio.h>
#include <string.h>
#fuses HS,NOWDT,NOLVP,NOBROWNOUT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)
#bit RCSTA_cren=0x18.4
#bit RCSTA_over=0x18.1

char recepcion;
short int activado=0;
// funcion de espera
void wait (long int y)
{
long int i,x;
   for (x=0;x<y;x++)
      for (i=0;i<y;i++);
}
// INTERRUPCION DE LA UART POR RX
#int_RDA
void RDA_isr()
{
//recibimos comando
recepcion=getc();
//hacemos ECO
printf(recepcion);
//Esperamos 30 segundos de llamada, solo recogiendo el primer caracter de llamada
delay_ms(30000);
// comprobamos que es señal de ring
if (recepcion == "R")
   {
   if (activado == 0) //activamos alarma si es asi
      {
      printf("Alarma activada!!!"Giño;
      activado = 1;
      }
   else
      {
      activado = 0;
      printf("Alarma desactivada!!!"Giño;
      }
   }
//esperamos 1 segundo para que se termine de transmitir los datos de alarma
delay_ms(1000);
//eliminamos posible error de overrun
if (RCSTA_over&&1) // miramos sihay overrun, si lo hay lo ponemos a 0
   {
   RCSTA_cren = 0;
   printf("RCSTA"Giño; // comprobacion de paso
   }
}

void main (void)
{

activado=0;
set_tris_a(0); // todo el puerto a salida
set_tris_c(0x80);
output_bit (pin_a5,1); // comprobacion de paso
printf("Iniciando el sistema...."Giño; // comprobacion de paso
delay_ms(1000); // esperamos final de transmision
if (RCSTA_over&&1) // miramos sihay overrun, si lo hay lo ponemos a 0
   {
   RCSTA_cren = 0;
   printf("RCSTA"Giño; // comprobacion de paso
   }
//Habilitacion de interrupciones RS232
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

for(;Giño // bucle infinito
   {
      printf(".."Giño;//comprobacion de paso
      if (activado == 1) //verificacion de activacion de alarma
         output_bit(pin_a5,1);
      if (activado == 0)
         output_bit(pin_a5,0);
      while ((input(pin_b7)==0)&&(activado==1)) //si la alarma esta activa y el interruptor tambien salta!
         {
         printf("ATD123456789;"Giño; //envio de comandos AT
         putc(0x0d);
         delay_ms(30000);
         printf("ATH"Giño;
         putc(0x0d);
         delay_ms(5000);
         }   
   }

}


Bueno como no sabeis de que va esta aplicacion os la digo en un plis para que la entendais, en principio es una alarma pero que se activa y desactiva cuando se llama a un numero de telefono movil. El puerto USART esta conectado al movil y el pic transmite comandos AT de llamada y cuelgue (proximamente hasta mensajes jeje SMS), con lo que si se detecta que el pin b7 tiene un estado bajo (dependera del sensor) enviara una llamada al numero que le indiquemos, esperara 30 segundos colgara y a los 5 segundos volvera a marcar si B7 sigue activo. si llamamos desde un telefono al pic, este se activara o se desactivara si es la segunda vez que le llaman.

Entonces aqui viene el problema, no consigo que se desactive la alarma....... no entra en la interrupcion RS232 y no se porque...... y lo que ya no me explico es que despues de toda la tarde, el cuelgue del pic fuera por el while (true) ¿? ademas he notado que el pic tarda en arrancar cerca de 2 minutos (sale el mensaje de inicializacion y pasa como unas 30 veces antes de pararse y estar 2 minutos parado sin hacer nada, luego vuelve a transmitir los puntos....¿?) En El primer acceso a interrupcion tarda mas de 30 segundos y el segundo acceso y sucesivos no lo hace... porque? todo esta monitorizado con el hyperterminal. Haber si alguien me puede echar una mano que llevo mas de 10 horas detras del puñetero problema y no  quiero acceder al puerto serie por sondeo sino por interrupcion. Gracias!!!!!!!!!!!
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #6 en: 08 de Septiembre de 2005, 12:33:00 »
Mira en el ejemplo del CCS.
EX_SISR.C en la carpeta Examples...
Tal vez te ayude, aunque me haces dudar que busques ayuda...GiñoGiño
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #7 en: 08 de Septiembre de 2005, 16:03:00 »
Gracias MLGsoft por tu intereres, efectivamente busco ayuda pero no me quedo parado esperando la solucion...., voy a mirar el fichero que me comentas, pero creo que ya lo he arreglado, la solucion la tiene la funcion KBHIT() seguido de la lectura del caracter que esta en el buffer, de esta manera el overrun no se produce y no queda colgado el programa Sonrisa

dejo el codigo que he usado (es trivial), en este caso no esta dentro de la interrupcion pero se puede poner una variable que diga que hay interrupcion...


if (KBHIT()) // vemos si hay caracter en el buffer de entrada
        caracter= getc(); // esta es la llamada a la interrupcion

Pues con esto se me han solucionado muchos problemas (por no decir todos), espero que a la gente tambien le ayude.

Con respecto a mi proyecto ya funciona al 50% con esta solucion, al menos se activa y se desactiva la alarma cuando llamo a la misma por GSM y me llama cuando hay un evento. Ahora estoy  tratando de descifrar los comandos AT para el envio de mensajes, pero esto es un mundo, cada telefono es de su padre y de su madre.. no se para que coño hacen standares.. si la gente se los salta a la ligera jeje..

gracias de nuevo y cualquier solucion es bien recibida. Un saludo.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #8 en: 08 de Septiembre de 2005, 16:55:00 »
Bueno aunque tarde, te adjunto los FAQS de CCS respecto a la reentrada y el uso de los Delay en las interrupciones...




Why do I get a "Interrupts disabled to prevent re-entrancy" warning?

Due to the limited hardware stack of the PIC a limitation of the CCS compiler is the disability to use recursion in functions. This drawback will affect customers if they try to call a function in an interrupt that is also called outside of an interrupt. When you see this warning message, the compiler is letting you know that you are calling a function inside an interrupt that is also called outside of the interrupt. To prevent accidental recursion the compiler will disable interrupts when you call that specific function outside of that interrupt.

A workaround is to include the function twice, so the code and variables exist in seperate blocks of code so there is no reentrancy. Also do not forget that if the function is included twice, all other functions called by this function will have to be called twice.

 How can I use a delay_XX() routine in an interrupt without disabling interrupts?

First, it is not good design practice to call delay_XX() routines inside your interrupt. Try to design your programs so interrupts take as little time as possible.

Second, read the FAQ about how the compiler prevents accidental reentrancy.

The internal CCS functions, such as the RS232 and delay_XX() functions, cannot be defined twice like normal C functions that are defined by the users. However, here is a work around to define two #use delay(clock=XXXXX) which in turn will create two delay_XX() functions in code space so there would be no reentrancy problems with interrupts:

(This is very similar to creating two serial ports).


#include <18F452.h>
#fuses HS,NOWDT,NOLVP,NODEBUG,NOPUT,NOBROWNOUT
#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7)

#use delay(clock=20000000)

#int_YOURINTERRUPT
void isr(void) {
   /*
     YOU CODE HERE
   */

   delay_ms(10);
}

#use delay(clock=20000000)

void main(void) {
   enable_interrupts(int_YOURINTERRUPT);
   enable_interrupts(GLOBAL);

   while(TRUE) {
      delay_ms(100);
     
      /*
         YOUR CODE HERE
      */
     
   }
}





Espero te sea de utilidad !!!Sonrisa GiganteSonrisa GiganteSonrisa Gigante
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: Comunicacion RS232... el micro se queda colgado....
« Respuesta #9 en: 08 de Septiembre de 2005, 17:14:00 »
Gracias de nuevo MLGSOFT por el detalle, he revisado el fichero que me has comentado antes y lo que me has comentado ahora, el tema del RS232 por lo que veo no esta muy conseguido aun, pero las notas me valen de gran ayuda, dejo mi programa, que al final l he vuelto a retocar (creo que he cambiado el programa 500 veces jajajaaj) y que ya funciona al menos como yo quiero.

#include <16f876a.h>
#include <stdio.h>
#include <string.h>
#fuses HS,NOWDT,NOLVP,NOBROWNOUT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use fast_io (C)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)

char recepcion;
short int activado=0;

#int_RDA
void interrupcion ()
{
recepcion=getc();
}

void RDA_isr()
{
// comprobamos que es señal de ring
if (recepcion == "R")
   {
   recepcion=NULL;
   delay_ms(10000);
   if (activado == 0) //activamos alarma si es asi
      {
      activado = 1;      
      }
   else
      {
      activado = 0;
      }
   }
}

void main (void)
{
int i;
activado=0;
set_tris_a(0); // todo el puerto a salida
set_tris_c(0x80);
output_bit (pin_a5,1); // comprobacion de paso
delay_ms(1000);
output_bit (pin_a5,0); // comprobacion de paso
enable_interrupts(global);
enable_interrupts(int_RDA);
for(;Giño // bucle infinito
   {
      RDA_isr();
      if (activado == 1) //verificacion de activacion de alarma
         output_bit(pin_a5,1);
      if (activado == 0)
         output_bit(pin_a5,0);
      while ((input(pin_b7)==1)&&(activado==1)) //si la alarma esta activa y el interruptor tambien salta!
         {
            for (i=0; i<5;i++)
            {
            printf("ATDXXXXXXXXX;"Giño; //envio de    comandos AT
            putc(0x0d);
            delay_ms(30000);
            printf("ATH"Giño;
            putc(0x0d);
            delay_ms(5000);
            }
         }
   }

}


muy simple pero funciona como quiero, y hace caso a las interrupciones jeje al final lo consegui, claro cuando dicen que pongas poco tiempo en las interrupciones.... jeje por algo sera aunque en 232 es normal, en cualquier momento te puede venir un dato y el micro tiene que estar preparado para ello(un dia de estos lo programare a bajo nivel el 232.. un dia de estos Giño )

Bueno lo dicho nunca es tarde si la dicha es buena, Gracias y un saludo.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P


 

anything