Autor Tema: Fallo curioso en recepcion RS232  (Leído 2404 veces)

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

Desconectado cucuruy

  • PIC10
  • *
  • Mensajes: 6
Fallo curioso en recepcion RS232
« en: 01 de Mayo de 2008, 16:50:41 »
Hola compañeros,
acudo a vosotros porque llevo dias enganchado con una cuestion y no hay manera de salir adelante.
Os comento:
estoy haciendo un proyecto con un 18F2550, conectado a un modem gsm por rs232 y al pc por usb, ademas de estar conectado al pc por 232 para monitorizar los valores que se envian entre pic y modem.

el pic envia un comando at y el modem responde, ambos comandos los visualizo en el pc, el pic recibe la respuesta y activa unas variables determinadas.

yo envio AT(CR) y el modem responde (CR)(LF)OK(CR)(LF), correcto.
envio AT+CPIN?(CR) y el modem responde (CR)(LF)+CPIN: SIM PIN(CR)(LF) y seguidamente envia (CR)(LF)OK(CR)(LF)

pues aqui tengo el fallo, yo en la pantalla lo visualizo, veo que el modem envia toda esa trama, pero el pic solo recibe (CR)(LF)+CPIN: SIM PIN(CR)(LF)(LF) <-- y ya esta.

he probado de agregar el parametro ERRORS en la directiva #use rs232 y el resultado sigue siendo erroneo, con el extraño resultado: +CPIN: SIM PIN(CR)(LF)(CR)(LF)?H(CR)(LF)OK(CR)(LF)

no se que es lo que puede fallar, la rutina de atencion a la interrupcion serie la veo bien...  no se

el programa tiene 1500 lineas, por lo que solo adjunto lo que creo q es relevante
os adjunto la cabecera:
Código: [Seleccionar]
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL3,CPUDIV3,VREGEN
#use delay(clock=24000000) //el cristal es de 12mhz pero el reloj es de 24mhz
#USE RS232(BAUD=9600,XMIT=PIN_C6,RCV=PIN_C7,stream=PC)

os adjunto la #int_rda:
Código: [Seleccionar]
#int_RDA
void serial_isr()             // =========== interrupcion puerto serie =========
{
   if(kbhit(PC))
   {
      add_buffer(getch(PC));     // lo recibo y lo añado al buffer de recepcion
   }
}
void add_buffer(char ab)     // añade caracter al buffer
{
   int i;
   modem.busy=1;
   tics232=0;
   tx232=1;
   
   buffaux[m]=ab;
   m++;
   
   switch((int)ab)
   {                          // (13)(10)OK(13)(10) -->  CR=13 y LF=10!!!!!!!
     
      case 13:
         // nada, para que el CR(13) no entre en default
         break;               
      case 10:                //si llega un LF(10)
         if(modem.resp==0)      //si llega el 1er LF(10)
         {
            modem.resp=1;
            posbuffer=0;
         }
         else                   //si llega el 2º LF(10) --> fin respuesta
         {
            modem.resp=0;
            // --- OK ---
            if((modem.respuesta[0]=='O')&&(modem.respuesta[1]=='K'))
            {
               modem.ok=1;
               dosr=0;
            }
            // --- ERROR ---
            if((modem.respuesta[0]=='E')&&(modem.respuesta[1]=='R'))   //en el primer if solo habran seguro 2 bytes
            {
               modem.error=1;
               dosr=0;
            }

            // --- +CPIN / +CSCA / +CMGS / +CMTI ---
            if((modem.respuesta[0]=='+')&&(modem.respuesta[1]=='C'))
            {
               dosr=1;
               // --- +CPIN ---
               if((modem.respuesta[2]=='P')&&(modem.respuesta[7]=='S')&&(modem.respuesta[8]=='I'))
               {
                  if(modem.respuesta[12]=='I')
                  {
                     modem.pin=2;      //+CPIN: SIM PIN
                  }
                  else
                  {
                     modem.pin=4;   //+CPIN: SIM PUK
                  }
               }
               else
               {
                  if((modem.respuesta[2]=='P')&&(modem.respuesta[7]=='R')&&(modem.respuesta[8]=='E'))
                  {
                     modem.pin=3;   //+CPIN: READY
                  }
                  else
                  {
                  // --- +CSCA ---
                     if((modem.respuesta[2]=='S')&&(modem.respuesta[3]=='C')&&(modem.respuesta[4]=='A'))
                     {
                        for(i=0;i<9;i++)
                        {
                           write_eeprom(i+4,modem.respuesta[i+11]);     //la escritura habria q sacarla d aki
                           delay_ms(7);
                           //+4 pq empieza en la posicion 4 de la eeprom
                           //+11 porque solo guardamos desde la posicion 11 del arreglo de la trama recibida
                           //+CSCA: "+34656000311",145
                        }
                        modem.csca=1;
                     }
                     else
                     {
                        // --- +CMGS ---
                        if((modem.respuesta[2]=='M')&&(modem.respuesta[3]=='G')&&(modem.respuesta[4]=='S'))
                        {
                           modem.cmgs=modem.respuesta[7];   //guardamos la posicion del mensaje
                        }
                        else
                        {
                           // --- +CMTI ---
                           if((modem.respuesta[2]=='M')&&(modem.respuesta[3]=='T')&&(modem.respuesta[4]=='I'))
                           {
                              modem.cmti=1;
                           }
                        }
                     }
                  }
               }
            }
            // ------- vaciado del buffer --------
               modem.respuesta[0]='\0';

            if(dosr==0)   //si solo es 1 respuesta
            {
               modem.busy=0;
            }
         }
         break;   //fin case 10 LF

      default:
         if(modem.resp==1) //solo leera caracteres despues del primer LF
         {
            modem.respuesta[posbuffer]=ab;  // añado caracter recibido al buffer
            posbuffer++;
            if(((int)ab)==62)      // si es '>' (3E)=62
            {
               modem.estesms=1;
               modem.resp=0;
            }
         }
   }
}

Muchas gracias por adelantado, cualquier pequeña ayuda será bienvenidisima jejej.
Salu2.

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
Re: Fallo curioso en recepcion RS232
« Respuesta #1 en: 01 de Mayo de 2008, 17:29:59 »
La verdad es extraño. He mirado por encima el codigo y unas cosillas:

En add_buffer haces buffaux[m]=ab;m++;  pero no haces ninguna comprobacion de si m ha llegado al limite fisico del array, lo cual puede tener consecuencias desconocidas. O al menos no lo muestras en el codigo.

Por otra parte, me parece que la rutina add_buffer le esta quitando bastante tiempo a la interrupcion 232. No se cual es la estructura general de tu programa, pero comentarte que en interrupciones "vastas" (porque add_buffer tiene bastante codigo), o programas con muchas interrupciones, o con un RS232 rapido mas un PIC lento, pasa que no siempre hemos recibido un unico caracter al entrar a INT_RDA. Puede que recibiesemos dos. O tres. O mas de cuatro, lo cual recae en buffer overrun, y a partir de ahi se jodio; hay que bajar el flag para volver a recibir.

Mi recomendacion (no se si sera la solucion pero bueno, te ahorrara disgustos):


#int_RDA
void serial_isr()             // =========== interrupcion puerto serie =========
{
   while(kbhit(PC))
   {
      add_buffer(getch(PC));     // lo recibo y lo añado al buffer de recepcion
   }
}

Bueno, aver si hay suerte. Salu2!

Desconectado cucuruy

  • PIC10
  • *
  • Mensajes: 6
Re: Fallo curioso en recepcion RS232
« Respuesta #2 en: 02 de Mayo de 2008, 02:43:47 »
Muchas gracias por la respuesta manex, esta tarde cuando llegue a casa hago la prueba.
Además, intentaré quitar peso a add_buffer, haciendo uso de algunos flags y haciendo el trabajo desde el main.

Salu2.

Desconectado cucuruy

  • PIC10
  • *
  • Mensajes: 6
Re: Fallo curioso en recepcion RS232
« Respuesta #3 en: 02 de Mayo de 2008, 14:42:51 »
Hola de nuevo,
he probado de cambiar el if por el while, y el resultado ha sido el mismo.
La solución la he encontrado vaciando, como bien me habias recomendado, la rutina de atencion a la interrupcion, dejandola asi:
Código: [Seleccionar]
#int_RDA
void serial_isr()             // =========== interrupcion puerto serie =========
{
   while(kbhit(PC))
   {
      add_buffer(getch(PC));     // lo recibo y lo añado al buffer de recepcion
   }
}

void add_buffer(char ab)     // añade caracter al buffer
{
   int i;
   modem.busy=1;
   tics232=0;
   tx232=1;
   
   buffaux[m]=ab;
   m++;
}

El switch lo manejo dentro del main, controlando un flag y una variable para su correcto funcionamiento.
Ahora recibo correctamente todos los caracteres, no se que deberia pasar antes para que se perdieran datos.

Bueno, muchas gracias por tu ayuda manex, y a los demas compañeros que han leido el post y han dedicado un minuto de su atencion.
Salu2.

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Fallo curioso en recepcion RS232
« Respuesta #4 en: 02 de Mayo de 2008, 15:01:04 »
Saludos! Chévere que resolviste tu problema amigo cucuruy!  :-/
Entonces, maestro Manex, la moraleja de esta historia es que debemos tratar de que nuestras rutinas de interrupciones sean lo más cortas posibles?  :-)

Ok nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado cucuruy

  • PIC10
  • *
  • Mensajes: 6
Re: Fallo curioso en recepcion RS232
« Respuesta #5 en: 05 de Mayo de 2008, 14:39:07 »
Hola de nuevo,
si que es recomendable quitar peso de las rutinas de interrupciones, pero en ocasiones se necesita hacer que esa rutina devuelva un valor despues de hacer las comparaciones y calculos necesarios, ese es mi caso.
Resulta que yo saqué la parte de comparación de los caracteres obtenidos por la int_rda, pero entonces me sucede que no puedo estar dentro de un while(lo que sea) esperando que una variable ligada al puerto serie sea modificada, ya que estas modificaciones ahora las hago desde el main.
En definitiva, no he resuelto mi problema.
Lo que tengo dentro de la interrupcion es necesario para el funcionamiento del programa, asi que debe haber alguna otra manera de corregir este error en la recepcion de caracteres por puerto serie.
A ver como lo soluciono, mi tutor del proyecto me va a echar a los perros.

Un saludo!