TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: sauron en 25 de Octubre de 2011, 23:16:40

Título: PIC "se cuelga" al recibir datos por USART
Publicado por: sauron en 25 de Octubre de 2011, 23:16:40
Hola compañeros foristas.

Me topé con éste obstáculo y les agradezco sus opiniones al respecto:

Tengo el Rx del USART de un 16f628A conectado "en paralelo" junto con el Rx de dos sendos dispositivos seriales (no PICs).

Ésto es debido a que deben recibir datos de forma remota y según el dato, cada uno debe hacer una función.

Resulta que el PIC funciona hasta que se mandan los datos para los otros dos dispositivos, se puede decir que cuando el PIC lee esos datos a los segundos "se cuelga", ya que no hace nada y hay que reiniciarlo.

He de acotar que se tiene la interrupción del USART activada, ya que en teoría, cuando llega el dato que le concierne al PIC, éste debe reconocerlo y ejecutar la función. He pensado que el PIC se debe saturar o algo parecido por el uso excesivo de la interrupción, pero no puedo desactivarla porque entonces como se le daría ordenes.

El problema es que solo hay una vía para que le lleguen los datos a los tres y por eso hay que tener a los tres en un nodo"escuchando" al mismo tiempo.

Alguna opinión? Gracias!
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: Diego E. en 25 de Octubre de 2011, 23:50:09
Hola amigo, alguna vez me pasaba con un USART que se bloqueaba y lo solucioné adicionando en la configuración del USART un timeout

Saludos.
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: jeremylf en 25 de Octubre de 2011, 23:51:25
tu codigo debe estar algo mal seguro.
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: MerLiNz en 26 de Octubre de 2011, 00:01:55
si tienes una interrupcion y no borras el flag de la interrupcion el codigo no sale de la interrupcion, por lo cual ahi tendrias un bucle infinito. La interrupcion solo funciona si tu quieres, poniendo el IE=0 que le pertenece ya no hace interrupcion y sigue recibiendo datos igualmente. Si pones tu codigo se podra ver el fallo mejor.
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: Nocturno en 26 de Octubre de 2011, 01:30:27
Entiendo que cuando el PIC entra en la interrupción y ve que el dato recibido no es para sí mismo, no lo procesa pero sigue leyéndolos, ¿verdad?

Me da la impresión de que podría llenarse el buffer si no lo estás leyendo.
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: alcubo01 en 26 de Octubre de 2011, 03:28:39


 Según cuentas, parece que cuelga cuando envias datos y esperas respuesta. ¿Podría ser que se cuelgue al enviar datos y no al recibirlos?

 ¿Tienes habilitada la interrupcion por Tx en la USART?
 
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: AngelGris en 26 de Octubre de 2011, 09:24:42
  Sería bueno que pongas el programa para ver que puede estar pasando. Aunque sea subir la parte de la interrupción así vemos como manejas las llegadas de datos.
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: rivale en 26 de Octubre de 2011, 09:31:30
  Sería bueno que pongas el programa para ver que puede estar pasando. Aunque sea subir la parte de la interrupción así vemos como manejas las llegadas de datos.

++; :mrgreen:

realmente pueden ser muchas cosas, pero lo mas facil es ver el codigo y te ayudaremos mas facilmente

Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: Suky en 26 de Octubre de 2011, 11:29:32
Por más que los datos sean para otro dispositivos, el microcontrolador debe leerlos y desecharlos en todo caso. Pero si no lo lees y ocurre un overflow, el módulo se bloquea y debes re-iniciarlo.


Saludos!
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: sauron en 26 de Octubre de 2011, 11:50:30
Vale gracias a todos, me alegra que les haya interesado, en realidad puede ser una aplicación útil para muchos.

Les voy a explicar más a fondo:

(IMAGEN A MODO DE EJEMPLO)

HAY UN ERROR EN LA IMAGEN, EL PIN TX DEL PIC VA CONECTADO AL SWITCH

(https://lh5.googleusercontent.com/-pXr5CE0aYnY/TqgYMGxAV3I/AAAAAAAAAfs/gRX5LWi6TRo/s640/foropic.jpg)

El pin Rx del PIC y de los dispositivos seriales están conectados en un solo nodo y los pines Tx van conectados a un Switch digital (74HC4066), el cual el PIC va a controlar, dónde según el dato que éste reciba, va a "suichear" y así permitir que el terminal Tx del dispositivo 1 o 2 se conecte al puerto serial.

Voy a ser lo más explícito posible respecto al código:

Código: [Seleccionar]
#include <16F628A.h>
#include <string.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                  //Code protected from reads
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection

#use delay(clock=4000000)
#use rs232(baud=9600, parity=N, bits=8, xmit=PIN_B2, rcv=PIN_B1) //manejo del RS232
#use fast_io(a)
#use fast_io(b)

char dato, BufferRx[6];
unsigned int i=0;
int1 BanderaComp=0;

//Tramas de 5 caracteres
char disp1[6]="xxxx$", disp2[6]="yyyy$", desactivar[6]="zzzz$";

// Rutina de Interrupcion por RX USART
#int_RDA
void RDA_isr(void)
{
 //Caracter de final: $ (HEX: 24)
 dato=0x00;
 if(kbhit())
 {
  dato=getc();
 }
 BufferRx[i]=dato;
 i++;
 if(dato==0x24)
 {
  BanderaComp=1;
  i=0;
 }
}

La idea es que cuando se reciba el caracter "$" indique el fin de la trama, luego dicha trama guardada en BufferRx, se compara:

Código: [Seleccionar]
void comprobacion()
{
 disable_interrupts(global);
  if(!strcmp(BufferRx, disp1)) //cuando la comparación NO es igual, retorna 1
 {
  output_high(PIN_B4);
 }
 if(!strcmp(BufferRx, disp2)) //cuando la comparación NO es igual, retorna 1
 {
  output_high(PIN_B5);
 }
 if(!strcmp(BufferRx, desactivar)) //cuando la comparación NO es igual, retorna 1
 {
   output_low(PIN_B4);
   output_low(PIN_B5);
 }
 enable_interrupts(global);
 BanderaComp=0;
 BufferRx = 0x00;
}

Los string: "disp1, disp2 y desactivar", son cadenas preestablecidas en el pic que son las que se reciben vía serial.

Y la función MAIN:

Código: [Seleccionar]
void main()
{

// Configuración inicial del PIC
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   set_tris_a(0x01);
   set_tris_b(0x02);
   BufferRx = 0x00;
   do
   {
     //PIC A LA ESPERA POR COMANDO SERIAL
    if(BanderaComp)
     comprobacion();
   }while(TRUE);
}

He de acotar que los dispositivos seriales tienen sendos programas (privados de su fabricante) para ser controlados.

OJO: El "suicheo" FUNCIONA correctamente, se realizó ésta operación hasta 30 veces seguidas y el PIC no tuvo problema, el detalle está cuando luego de que un dispositivo está conectado al puerto serial, se conecta a través de su programa de fabricante y empiezan a transmitirse sus datos, a los segundos el PIC se cuelga y hay que reiniciarlo.
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: Suky en 26 de Octubre de 2011, 11:54:54
Los buffer están mal declarados, si vas a guardar 6 caracteres, mínimo debe tener 7 lugares. Y al recibir, asegúrate de colocar el carácter '\0' para indicar finalización del string.

Saludos!
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: sauron en 26 de Octubre de 2011, 12:00:44
Los buffer están mal declarados, si vas a guardar 6 caracteres, mínimo debe tener 7 lugares. Y al recibir, asegúrate de colocar el carácter '\0' para indicar finalización del string.

Saludos!

Hola Suky.

La trama a manejar es de 5 caracteres, el error está en el código posteado (ya lo corregí) pero si está bien establecido en el original.


Vale orita observando sus comentarios y sobre el overflow, me he dado cuenta de que hay un desbordamiento del string BufferRx dentro de la interrupción, ya que su indice "i" solo se va a inicializar cuando llegue el caracter final.

Obviamente eso puede ser un problema verdad?
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: Suky en 26 de Octubre de 2011, 12:14:09
Obviamente eso puede ser un problema verdad?

Claro
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: sauron en 26 de Octubre de 2011, 12:23:17

Claro

Vale incluyo ésto para que se limpie el buffer y les comento:

Código: [Seleccionar]
#int_RDA
void RDA_isr(void)
{
 if(i>6)
 {
  i=0;
  BufferRx = 0x00;
 .
 .
Título: Re: PIC "se cuelga" al recibir datos por USART
Publicado por: sauron en 03 de Noviembre de 2011, 17:23:47
Efectivamente el problema era ese, tan simple... gracias a todos
Título: Re:PIC "se cuelga" al recibir datos por USART
Publicado por: Pelos en 20 de Agosto de 2020, 02:08:44
Hola a todos, estoy teniendo el mismo problema de sauron solo que no me ocurre un desbordamiento (o almenos eso creo).
Realizo la lectura de DNI´s y este mismo me da la orden de iniciar los otros procesos del micro, pero, si por accidente se lee la DNI mientras se empezó a ejecutar un proceso del micro este se bloquea.
(Los datos de la DNI llegan por usart)

He deshabilitado las interrupciones intentando que solo funcione la interrupción por serial mientras se solicita la DNI pero aun asi, sigue sin funcionar.

El código del programa completo es extenso asi que pondré una parte y si alguien puede ayudarme y considera necesario otra, estaré atento.

Gracias

Código: CSS
  1. #int_rda
  2. void serial(){
  3.  if(kbhit(hardw)){
  4.     for (k=0;k<80; k++){
  5.         trama[k]=getchar(hardw);
  6.         if(trama[k]==9){
  7.            nueve++;
  8.            if(nueve==5){
  9.               if(trama[k-1]==9){
  10.                  error=1;
  11.               }else{
  12.                 error=0;
  13.               }
  14.           }
  15.         }
  16.        if(trama[k]==10){
  17.           trama[k]=0;            
  18.           break;
  19.       }
  20.    }              
  21.  }
  22.  permiso=1;
  23. }

así es como ejecuto la lectura del puerto y lo almaceno en el buffer llamado "Trama".
Título: Re:PIC "se cuelga" al recibir datos por USART
Publicado por: remi04 en 20 de Agosto de 2020, 04:00:14
Hola a todos, estoy teniendo el mismo problema de sauron solo que no me ocurre un desbordamiento (o almenos eso creo).
Realizo la lectura de DNI´s y este mismo me da la orden de iniciar los otros procesos del micro, pero, si por accidente se lee la DNI mientras se empezó a ejecutar un proceso del micro este se bloquea.
(Los datos de la DNI llegan por usart)

He deshabilitado las interrupciones intentando que solo funcione la interrupción por serial mientras se solicita la DNI pero aun asi, sigue sin funcionar.

El código del programa completo es extenso asi que pondré una parte y si alguien puede ayudarme y considera necesario otra, estaré atento.

Gracias

Código: CSS
  1. #int_rda
  2. void serial(){
  3.  if(kbhit(hardw)){
  4.     for (k=0;k<80; k++){
  5.         trama[k]=getchar(hardw);
  6.         if(trama[k]==9){
  7.            nueve++;
  8.            if(nueve==5){
  9.               if(trama[k-1]==9){
  10.                  error=1;
  11.               }else{
  12.                 error=0;
  13.               }
  14.           }
  15.         }
  16.        if(trama[k]==10){
  17.           trama[k]=0;            
  18.           break;
  19.       }
  20.    }              
  21.  }
  22.  permiso=1;
  23. }

así es como ejecuto la lectura del puerto y lo almaceno en el buffer llamado "Trama".

 Seguramente sí que se desborda el fifo. Durante esos procesos basta que utilices un delay_ms() para que desborde. Sobre todo si son tramas lo que viene por el usart.

   Kbhit en la interrupción no parece tener sentido. Si entra en la interrupción es por que se ha recibido un carácter si o si.  Aunque esto no es problema tampoco que uses kbhit ahí, pero lo veo absurdo.

   Para evitar desbordamientos del fifo Lo que puedes hacer es instar el bit CREN con la macro #bit y la dirección del registro RCSTA de tu micro que no se cual es.  Si la dirección es por ejemplo 0x0a3 (es un ejemplo), y el bit CREN es el 4 tienes que instarlo en la cabecera de la siguiente forma:

   
Código: C
  1. #bit CREN=0x0a3.4

  También puedes instarla mediante variables de entorno usando getenv();

Código: C
  1. #bit CREN=getenv(“BIT:CREN”)

   Una vez que tienes esto lo que haces es deshabilitar CREN mientras están en los procesos y habilitarlo solamente cuando el programa esté en disposición de recibir.

 Es una forma de tener un control total del puerto si la interrupción no puede ser atendida con la suficiente rapidez.

  Al poner CREN a 0 prohíbes la recepción de datos y además reseteas el módulo de recepción y todas las banderas de los errores que haya activos.  Si había desbordado, esto reseteara todo y luego al volver a poner CREN a 1 volverá a recibir.

  Como usarlo depende de cómo sea el flujo del programa y la periodicidad con la que llegan las tramas.

  Saludos.