Autor Tema: PIC + GPS + LCD: problema rs232 con un timer  (Leído 4210 veces)

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

Desconectado abarth

  • PIC10
  • *
  • Mensajes: 6
PIC + GPS + LCD: problema rs232 con un timer
« en: 03 de Septiembre de 2010, 10:04:08 »
Buenas tardes a todos, es la primera vez que escribo en el foro después de varios años leyendo (... y aprendiendo) por lo que pido disculpas si me dejo atrás datos importantes para entender mi cuestión.

Para ponerles en situación, lo que tengo entre manos ahora es un modulo GPS de Parallax conectado por RS232 a un PIC 18F4550 el cual, por ahora, simplemente lee la hora UTC del GPS y la muestra en pantalla LCD.

Como ya saben esta hora UTC del GPS tiene resolución de segundos, cuando para este proyecto necesito tener décimas de segundo o centésimas si fuera posible. El caso es que decido hacer hh:mm:ss por un lado a través del GPS y las décimas a través de un timer. Por separado, todo funciona, el LCD muestra la hora UTC del GPS y el timer cuenta hasta 99 a ritmo (más o menos) de centésimas de segundo. Pero cuando junto los programas las décimas y centésimas permanecen inmóviles hasta que se renueva el segundero de la hora UTC... no se si me explico  :oops:

Por alguna razón que desconozco las décimas o centésimas no se renuevan al ritmo que deberían ir como si el programa se quedara siempre esperando un segundo cuando toma los datos del GPS. El caso es que el timer cuenta bien, ya que muestra centésimas diferentes  cada x centésimas de forma constante (aun no está calibrado).

Les dejo el código sencillo del programa por si me dan alguna luz:

Código: [Seleccionar]
#include <18F4550.h>
#fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN
#use delay (clock=48000000)
int i;
#include   <lcd.c>                              //Incluye las rutinas de manejo del LCD
#include   <GPS28500.h>                //Incluye funciones de manejo del GPS

#use fast_io(A)
#use fast_io(D)
Setup_adc_ports( NO_ANALOG );

int8 h0=0,h1=0,m0=0,m1=0,s0=0,s1=0,d0=0;
   
#INT_TIMER1
void decima()
   {
   SET_TIMER1 (15575);
   d0++;
   if (d0>99)
      {
      d0=0;
      }
   }

void main ()
   {
   lcd_init();
   
   SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_2);
   SET_TIMER1 (15575);
   ENABLE_INTERRUPTS(INT_TIMER1);
   ENABLE_INTERRUPTS(GLOBAL);
   
   while (TRUE)
      {   
      RxGPS();                                  //Lee las tramas GGA y RMC del GPS
      GPS_Time();                               //Obtiene la hora de la trama GGA
     
      h1=GPS_Buffer[0];
      h0=GPS_Buffer[1];
      m1=GPS_Buffer[2];
      m0=GPS_Buffer[3];
      s1=GPS_Buffer[4];
      s0=GPS_Buffer[5];                         //Memoriza hora en variables
         
      lcd_gotoxy(4,1);
      printf(lcd_putc,"%1x%1x:%1x%1x:%1x%1x,%02u",h1,h0,m1,m0,s1,s0,d0);
      }
   }

Y el del archivo de la librería GPS28500 facilitado por Microsistemas Programados:

Código: [Seleccionar]
/************************************************************************************************************************
                                    GPS_28500_PIC16.h
                                 Autor: Mikel Etxebarria
                        (c) Ingeniería de Microsistemas Programados S.L.
                                 www.microcontroladores.com
                                    Abril Bilbao 2010

Conjunto de funciones implementadas en C para PIC16 para la gestión del receptor GPS 28500 (Polstar PMB-248).
Se asume que la comunicación con el receptor GPS se realiza vía serie por software.

RxGGA()       Espera a recibir del GPS la trama GGA que la almacena en un buffer con inicio 0x190 del banco 3. Se
            obtiene información de los siguientes campos: Hora, Latitud, Longitud, Calidad, Nº de satélites y altura
            sobre el nivel de mar.

RxRMC()       Espera a recibir del GPS la trama RMC que se almacena en el buffer con inicio en 0x1C5 del banco 3.
            Se obtiene información de los siguientes campos: Velocidad y fecha.

RxGPS()       Esta función recibe del GPS y registra las tramas GGA y RCM con la información de:
            Hora UTC, latitud, longitud, calidad de la señal, nº de satélites, altura, velocidad y fecha

GPS_Time()       Devuelve en GPS_Buffer la hora UTC actual en formato hhmmss. Si el campo de hora
            estuviera vacío, el GPS_Buffer se llena con el carácter '-'

GPS_Date()       Devuelve en GPS_Buffer la fecha UTC actual en formato ddmmaa. Si el campo de fecha
            estuviera vacío, el GPS_Buffer se llena con el carácter '-'

GPS_Signal()    Devuelve en GPS_Buffer un carácter que expresa el estado de la señal: '1' (0x31)=
            señal válida; '0' (0x30)= señal no válida

GPS_Sat()       Devuelve en GPS_Buffer dos caracteres (xx) que representan el número de satélites
            visibles en un momento dado

GPS_Alt()       Devuelve en GPS_Buffer 7 caracteres en formato xxxxx.x que representan la altura en metros
            respecto al nivel del mar

GPS_Vel_N()      Devuelve en GPS_Buffer 5 caracteres en formato xxx.x que representan la velocidad en
            en nudos

GPS_Vel_K()    Devuelve en GPS_Buffer 5 caracteres en formato xxx.x que representan la velocidad en
            en km/h. Para ello se multiplican los nudos por la constante 1.85

GPS_Lat_O()    Devuelve en GPS_Buffer 1 carácter ('N' o 'S') que expresa la orientación Norte/Sur
            en la latitud

GPS_Lat_D()    Devuelve en GPS_Buffer 9 caracteres en formato xxxx.xxxx que representan la
            latitud en decimal

GPS_Lon_O()    Devuelve en GPS_Buffer 1 carácter ('O' o 'W') que expresa la orientación Este/Oeste
            en la longitud   

GPS_Lon_D()      Devuelve en GPS_Buffer 10 caracteres en formato xxxxx.xxxx que representan la
            longitud en decimal

GPS_Lat_S()    Devuelve en GPS_Buffer  caracteres en formato ggmmss.s que representan la
            latitud en sexagesimal (ggºmm'ss.s")

GPS_Lon_S()    Devuelve en GPS_Buffer  caracteres en formato gggmmss.s que representan la
            longitud en sexagesimal (gggºmm'ss.s") */


//Configura el canal GPS de comunicaciones serie por software, con el GPS #28500 de Parallax
#use rs232(baud=4800,xmit=PIN_C0,rcv=PIN_C0,force_sw,stream=GPS)

char GPS_Rx_GGA[65];               //Buffer de recepción de la trama GGA
#locate GPS_Rx_GGA=0x190            //Dirección de inicio del buffer GPS_Rx_GGA (0x190 banco 3)
char GPS_Rx_RMC[20];               //Buffer de recepción de la trama RMC
#locate GPS_Rx_RMC=0x1C6            //Dirección de inicio del buffer GPS_Rx_RMC (0x1c6 banco 3)
char GPS_Buffer[11];               //Buffer de salida (11 bytes máx.)                 
const char Trama_GGA[7]= {"$GPGGA"};   
const char Trama_RMC[7]= {"$GPRMC"};   
int w_f;

/*********************************************************************************************
Campo_Vacio() Esta función se ejecuta cuando se detecta que un determinado campo de una trama
está vacío (comienza con ','). En este caso las 10 posiciones del GPS_Buffer se cargan con '-' */

void Campo_Vacio()
{
   int i;
   for(i=0;i<11;i++)
      GPS_Buffer[i]='-';
}

/*********************************************************************************************
W_Buffer() Escribe un caracacter en la siguiente posición de GPS_Buffer */

void W_Buffer(char dato)
{
   GPS_Buffer[w_f]=dato;
   w_f++;
}

/*********************************************************************************************
GPS_Copy_RMC() Esta rutina copia los bytes de un determinado campo del buffer de recepción de la
trama RMC sobre el buffer de salida GPS_Buffer. N_Char debe contener el número de bytes a copiar
y Campo el número del campo deseado*/

void GPS_Copy_RMC(int N_Char,int Campo)
{
/*Calcular la posición del índice en función de los campos que hay que saltar en la trama RMC
para alcanzar el deseado */
   int i,b=0;
   for(i=0;i<Campo;i++)            //Nº de campos a saltar
      {
      while(GPS_Rx_RMC[b]!=',')      //Si no es fin de campo..   
         b++;                  //Siguiente carácter
      b++;                     //Siguiente campo
      }
//Copia el campo deseado sobre el buffer GPS_Buffer
   i=0;
   for(i=0;i<N_Char;i++)            //Nº de caracteres a copiar
      {
      GPS_Buffer[i]=GPS_Rx_RMC[b];   //Copia un carácter
      if(GPS_Buffer[i]==',')
         {
         Campo_Vacio();
         break;
         }
      b++;                     //Siguiente carácter
      }
}     

/*********************************************************************************************
GPS_Copy_GGA() Esta rutina copia los bytes de un determinado campo del buffer de recepción de la
trama GGA sobre el buffer de salida GPS_Buffer. N_Char debe contener el número de bytes a copiar
y Campo el número del campo deseado*/

void GPS_Copy_GGA(int N_Char,int Campo)
{
/*Calcular la posición del índice en función de los campos que hay que saltar en la trama GGA
para alcanzar el deseado */
   int i,b=0;
   for(i=0;i<Campo;i++)            //Nº de campos a saltar
      {
      while(GPS_Rx_GGA[b]!=',')      //Si no es fin de campo..   
         b++;                  //Siguiente carácter
      b++;                     //Siguiente campo
      }
//Copia el campo deseado sobre el buffer GPS_Buffer
   i=0;
   for(i=0;i<N_Char;i++)            //Nº de caracteres a copiar
      {
      GPS_Buffer[i]=GPS_Rx_GGA[b];   //Copia un carácter
      if(GPS_Buffer[i]==',')
         {
         Campo_Vacio();
         break;
         }
      b++;                     //Siguiente carácter
      }
}

/********************************************************************************************************
RxGGA() Espera a recibir del GPS la trama GGA que la almacena en un buffer con inicio 0x190 del banco 3. Se
obtiene información de los siguientes 8 campos: Hora, Latitud, Longitud, Calidad, Nº de satélites, dilución
horizontal y altura sobre el nivel de mar. */

void RxGGA()
{
   int i;
RxGGA_1:                        //Espera a recibir la cabecera $GPGGA
   for(i=0;i<6;i++)               
      {
      if(getc(GPS)!=Trama_GGA[i])      //Recibe carácter
         goto RxGGA_1;            //Si no es de cabecera, volver a empezar
      }
   i=0;
   do                           //Recibe la trama GGA hasta un CR (0x0d)
      {
      GPS_Rx_GGA[i]=getc(GPS);      //Recibe carácter y almacena en el buffer
      i++;
      }while(GPS_Rx_GGA[i-1] != 0x0d);//Si no es CR, seguir recibiendo
}

/*********************************************************************************************************
RxRMC() Espera a recibir del GPS la trama RMC que se almacena en el buffer con inicio en 0x1C6 del banco 3.
Se obtiene información de los siguientes 3 campos: Velocidad, ángulo en curso y fecha UTC. */

void RxRMC()
{
   int i;
RxRMC_1:                        //Espera a recibir la cabecera $GPRMC
   for(i=0;i<6;i++)
      {
      if(getc(GPS)!=Trama_RMC[i])      //Recibe carácter
         goto RxRMC_1;            //Si no es de cabecera, volver a empezar
      }
/*Como sólo nos interesa los campos de  velocidad, ángulo y fecha, nos saltamos los 6 primeros campos de la
trama RMC. Cada campo finaliza con ','*/
   for(i=0;i<6;i++)               //Nº de campos a saltar
      while(getc(GPS)!=',');         //Saltar un campo

//Recoger la información de los campos de velocidad, ángulo y fecha hasta el carácter 0x0d de fin de trama
   i=0;
   getc(GPS);
   do                           //Recibe la trama RMC hasta un CR (0x0d)
      {
      GPS_Rx_RMC[i]=getc(GPS);      //Recibe carácter y almacena en el buffer
      i++;
      }while(GPS_Rx_RMC[i-1] != 0x0d);//Si no es CR, seguir recibiendo
}

/*********************************************************************************************
RxGPS() Esta función recibe del GPS y registra las tramas GGA y RMC con la información de los
campos correspondientes a cada trama */

void RxGPS()
{
   RxGGA();
   RxRMC();
}

/*********************************************************************************************
GPS_Time() Devuelve en GPS_Buffer la hora UTC actual en formato hhmmss. Si el campo de hora
estuviera vacío, el GPS_Buffer se llena con el carácter '-' */

void GPS_Time()
{
   GPS_Copy_GGA(6,1);               //Obtiene 6 bytes del campo 1 de la hora en la trama GGA
}

/*********************************************************************************************
GPS_Date() Devuelve en GPS_Buffer la fecha UTC actual en formato ddmmaa. Si el campo de hora
estuviera vacío, el GPS_Buffer se llena con el carácter '-' */

void GPS_Date()
{
   GPS_Copy_RMC(6,3);               //Obtiene 6 bytes del campo 3 de la fecha en la trama RMC
}

/*********************************************************************************************
GPS_Signal() Devuelve en GPS_Buffer un carácter que expresa el estado de la señal: '1' (0x31)=
señal válida; '0' (0x30)= señal no válida */

void GPS_Signal()
{
   GPS_Copy_GGA(1,6);               //Obtiene 1 byte del campo 6 de la señal en la trama GGA
}

/*********************************************************************************************
GPS_Sat() Devuelve en GPS_Buffer dos caracteres (xx) que representan el número de satélites
visibles en un momento dado */

void GPS_Sat()
{
   GPS_Copy_GGA(2,7);               //Obtiene 2 bytes del campo 7 del nº de sat. en la trama GGA
}

/**********************************************************************************************
GPS_Alt() Devuelve en GPS_Buffer 7 caracteres en formato xxxxx.x que representan la altura en metros
respecto al nivel del mar */

void GPS_Alt()
{
   GPS_Copy_GGA(7,9);               //Obtiene 7 bytes del campo 9 con la altura en la trama GGA
}

/**********************************************************************************************
GPS_Vel_N() Devuelve en GPS_Buffer 5 caracteres en formato xxx.x que representan la velocidad en
en nudos */

void GPS_Vel_N()
{
   GPS_Copy_RMC(5,1);               //Obtiene 5 bytes del campo 1 con la velocidad en la trama RMC
}

/**********************************************************************************************
GPS_Vel_K() Devuelve en GPS_Buffer 5 caracteres en formato xxx.x que representan la velocidad en
en km/h. Para ello se multiplican los nudos por la constante 1.85 */

void GPS_Vel_K()
{
   int16 n1,n2,n3;
   int32 Km_h;
   GPS_Copy_RMC(5,1);               //Obtiene 5 bytes del campo 1 con la velocidad en la trama RMC

//Empezamos por convertir los nudos, representados en ASCII, a un valor decimal
   n1=GPS_Buffer[0]&0x0f;
   n1=n1*100;                     //Convierte las centenas
   n2=(GPS_Buffer[1]&0x0f)*10;         //Convierte las decenas
   n3=n1+n2+(GPS_Buffer[2]&0x0f);      //Convierte las unidades

//Los nudos se multiplican por 185  para pasar a Km/H y a continuación se almacenan en GPS_Buffer   
   Km_h=n3*185;                  //Calcula los Km/h
   w_f=0;   
   printf(W_Buffer,"%5.2w",Km_h);      //Almacena en GPS_Buffer con formato xxx.x
 }

/**********************************************************************************************
GPS_Lat_O() Devuelve en GPS_Buffer 1 carácter ('N' o 'S') que expresa la orientación Norte/Sur
en la latitud      */

void GPS_Lat_O()
{
   GPS_Copy_GGA(1,3);               //Obtiene 1 byte del campo 3 con la orientación en latitud de la trama GGA
}

/**********************************************************************************************
GPS_Lat_D() Devuelve en GPS_Buffer 9 caracteres en formato xxxx.xxxx que representan la
latitud en decimal */

void GPS_Lat_D()
{
   GPS_Copy_GGA(9,2);               //Obtiene 9 bytes del campo 2 con la latitud de la trama GGA
}

/**********************************************************************************************
GPS_Lon_O() Devuelve en GPS_Buffer 1 carácter ('O' o 'W') que expresa la orientación Norte/Sur
en la longitud      */

void GPS_Lon_O()
{
   GPS_Copy_GGA(1,5);               //Obtiene 1 byte del campo 5 con la orientación en longitu de la trama GGA
}

/**********************************************************************************************
GPS_Lon_D() Devuelve en GPS_Buffer 9 caracteres en formato xxxxx.xxxx que representan la
longitud en decimal */

void GPS_Lon_D()
{
   GPS_Copy_GGA(10,4);               //Obtiene 10 bytes del campo 4 con la longitud de la trama GGA
}

/**********************************************************************************************
GPS_Lat_S() Devuelve en GPS_Buffer  caracteres en formato ggmmss.s que representan la
latitud en sexagesimal (ggºmm'ss.s") */

void GPS_Lat_S()
{
   int16 n1,n2,n3,n4;
   float segundos;
   GPS_Copy_GGA(9,2);               //Obtiene 9 bytes del campo 2 con la latitud de la trama GGA

/*Convierte los carácteres ASCII que representan los segundos, a su equivalente en decimal */
   n1=GPS_Buffer[5]&0x0f;
   n1=n1*1000;                     //Convierte las unidades de millar
   n2=GPS_Buffer[6]&0x0f;
   n2=n2*100;                     //Convierte las centenas
   n3=(GPS_Buffer[7]&0x0f)*10;         //Convierte las decenas
   n4=n1+n2+n3+(GPS_Buffer[8]&0x0f);   //Convierte las unidades

//Convierte a sexagesimal multiplicando por 0.006
   segundos=n4*0.006;
   w_f=4;
   printf(W_Buffer,"%03.1f",segundos);   //Almacena en GPS_Buffer con formato xx.x
}

/**********************************************************************************************
GPS_Lon_S() Devuelve en GPS_Buffer  caracteres en formato gggmmss.s que representan la
longitud en sexagesimal (ggºmm'ss.s") */

void GPS_Lon_S()
{
   int16 n1,n2,n3,n4;
   float segundos;
   GPS_Copy_GGA(10,4);               //Obtiene 10 bytes del campo 4 con la longitud de la trama GGA

/*Convierte los carácteres ASCII que representan los segundos, a su equivalente en decimal */
   n1=GPS_Buffer[6]&0x0f;
   n1=n1*1000;                     //Convierte las unidades de millar
   n2=GPS_Buffer[7]&0x0f;
   n2=n2*100;                     //Convierte las centenas
   n3=(GPS_Buffer[8]&0x0f)*10;         //Convierte las decenas
   n4=n1+n2+n3+(GPS_Buffer[9]&0x0f);   //Convierte las unidades

//Convierte a sexagesimal multiplicando por 0.006
   segundos=n4*0.006;
   w_f=5;
   printf(W_Buffer,"%03.1f",segundos);   //Almacena en GPS_Buffer con formato xx.x
}

Gracias anticipadas por cualquier aportación... saludos.


Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #1 en: 03 de Septiembre de 2010, 11:35:33 »
Yo creo que el valor de las décimas (d0) lo tenés que mostrar dentro de tu rutina de interrupción del timer1.
Así, cada vez que cambia el valor, lo mostrás.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado abarth

  • PIC10
  • *
  • Mensajes: 6
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #2 en: 06 de Septiembre de 2010, 16:50:35 »
Gracias Angel por la respuesta.

Así es, si pongo el printf dentro de la interrupción si se renuevan continuamente los decimales en el LCD.

Lo que no me explico es cómo el mismo programa, sin el código de consulta del GPS, si muestra las décimas en el LCD sin que haga falta poner el printf dentro del timer... cuando son tareas que no tienen nada que ver la una con la otra.

El asunto es que el segundo paso del proyecto es hacer un registro de horario activado por una entrada externa... y si pongo el código dentro del main no coge las décimas, si lo pongo dentro del timer no coge las horas, minutos y segundos y si lo pongo en los dos se vuelve loco...

Igual me estoy equivocando en el método de meterle decimales a ese reloj horario... y hay maneras más fáciles.

Bueno, paciencia, seguimos en ello... agradezco cualquier aportación.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #3 en: 06 de Septiembre de 2010, 19:07:38 »

Así es, si pongo el printf dentro de la interrupción si se renuevan continuamente los decimales en el LCD.

Lo que no me explico es cómo el mismo programa, sin el código de consulta del GPS, si muestra las décimas en el LCD sin que haga falta poner el printf dentro del timer... cuando son tareas que no tienen nada que ver la una con la otra.

Sin la consulta sobre el GPS te muestra las décimas porque no hacés otra cosa que mostrar los decimales constantemente (incluso cuando no hay cambio), al no perder tiempo en otra cosa siempre pude mostrar los cambios de decimales.

Con la consulta sobre el GPS, si la misma dura más de una décima siempre va a haber valores decimales que no vas a llegar a mostrar. Y si suponemos que la consulta lleva tanto tiempo como 1 segundo, ahí es casi seguro que siempre vas a ver el mismo valor decimal sobre el LCD.

Por eso me parece la usar el printf dentro de la interrupción es la mejor opción.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #4 en: 06 de Septiembre de 2010, 21:03:15 »
Hola.

Para actualizar el dato del Timer, usa algun flag para avisar que ya hay que actualizar el dato. La idea de poner el printf() dentro de la interrupción no es muy buena, ya que toma mucho tiempo y no es recomendable.

Saludos
El papel lo aguanta todo

Desconectado abarth

  • PIC10
  • *
  • Mensajes: 6
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #5 en: 07 de Septiembre de 2010, 08:26:12 »
Gracias Angel y MLO por las aportaciones.

Creo que, como dice Angel, la comunicación con el GPS es lenta y el programa pasa en esas líneas demasiado tiempo. Sin la consulta GPS todo va correcto. Es más, para confirmarlo hago comprobaciones con la entrada externa que memoriza la hora, y esta solo funciona cuando el LCD pasa de un segundo a otro...  :( es decir, que la consulta debe durar casi un segundo y cuando termina sigue con los procesos cortos de memoria de tiempos y de lcd, volviendo a la consulta nuevamente.

Estoy mirando el tema de las banderas o flags como dice MLO, pero me temo que va a ser lo mismo, si no se simplifica la comunicación RS232 con el GPS no habrá forma de hacer lo que pretendo.

Hasta he intentado ponerle un condicional (IF) a la consulta del GPS para que no la haga continuamente y deje al programa trabajar, pero al ser tan larga cuando termina el proceso de consulta el condicional ya se ha cumplido y vuelve a realizar la consulta.

Me parece cuanto menos extraño que la consulta sea justamente casi 1 segundo... yo creo que en la consulta hay un parámetro que le hace esperar a que se renueve la hora y no sale de ahi, pero no encuentro nada en la librería de GPS que pueda hacer algo parecido...

... lo dicho, creo que habrá que trastear con la librería de comunicación rs232 con el GPS a ver que se puede conseguir... simplificarla o algo por el estilo. Gracias nuevamente.
« Última modificación: 07 de Septiembre de 2010, 08:38:04 por abarth »

Desconectado abarth

  • PIC10
  • *
  • Mensajes: 6
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #6 en: 07 de Septiembre de 2010, 09:24:06 »
Bueno, creo que he dado con la parte de la librería del GPS que provoca la espera del segundo... en mi caso es el void RxGGA() aunque en el código que puse inicialmente era el void RxGPS()... les dejo la parte concreta de la librería GPS28500:

Código: [Seleccionar]
void RxGGA()
{
int i;
RxGGA_1:                        //Espera a recibir la cabecera $GPGGA
   for(i=0;i<6;i++)              
      {
      if(getc(GPS)!=Trama_GGA[i])      //Recibe carácter
         goto RxGGA_1;            //Si no es de cabecera, volver a empezar
      }
   i=0;
   do                           //Recibe la trama GGA hasta un CR (0x0d)
      {
      GPS_Rx_GGA[i]=getc(GPS);      //Recibe carácter y almacena en el buffer
      i++;
      }while(GPS_Rx_GGA[i-1] != 0x0d);//Si no es CR, seguir recibiendo
}

El GPS, desgraciadamente, renueva cada 1 segundo, por lo que en este caso manda la cabecera Trama_GGA cada segundo y si lo que recibe no es la cabecera que busca pues vuelve a empezar con el goto RxGGA_1. El proceso, lógicamente, dura un segundo y no sale de ahí hasta que encuentra la cabecera. A ver si consigo leer la cabecera de otra forma sin que esté ahi continuamente en ese bucle comprobando...
« Última modificación: 07 de Septiembre de 2010, 09:27:02 por abarth »

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #7 en: 07 de Septiembre de 2010, 20:47:56 »
Hola.

Para hacer lo que quieres debes usar la interrupción serial del PIC. De esa manera el PIC puede dedicarse a hacer otras rutinas y atiende la recepción serial solo cuando el GPS envía la trama.

Saludos

El papel lo aguanta todo

Desconectado abarth

  • PIC10
  • *
  • Mensajes: 6
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #8 en: 08 de Septiembre de 2010, 18:03:54 »
Buenas nuevamente, gracias MLO por la paciencia.

La verdad que últimamente no doy una de frente... porque ahora no hay forma de que haga la interrupción, hay algún concepto que lo entiendo mal o no se que estoy haciendo y ya no se ni cuantos post del foro me he repasado.

Mi intención era usar el INT_RDA para detectar una entrada de dato en el RS232, pero por lo que he leido no funciona por software (que es como viene configurado el RS232 en la librería del GPS) sino por hardware.

Dicho y hecho, con el force_sw el PIC recibe los datos del GPS pero no hace la interrupción como temíamos.

Vamos a hacerlo por hardware: le quito el force_sw al #use rs232, resultado: LCD en blanco, algo va mal. Incluso si configuro puerto C con el #use fast_io(C) y el set_tris para que C7 sea entrada y C6 salida ( set_tris_c(0b10000000); )pero nada. Estoy usando ahora el C7 como RX y el C6 como TX por que es como vienen en el patillaje del 18F4550.

Cambio de tercio, decido cambiar las patillas a C0 para RX y C1 para TX y no va sin el force_sw, pero configurando el puerto C con el #use fast_io(C) y el set_tris para que C0 sea entrada y C1 salida ( set_tris_c(0b00000001); ) entonces resucita el LCD, se reciben los datos del GPS pero sigue sin hacer la interrupción RDA.

He resumido la interrupción RDA para que simplemente incremente el valor (variable j) y lo muestre en el LCD para simplemente saber que hace la interrupción y a partir de ahi trabajar con la cadena que envíe el GPS. He hecho tantas pruebas en el código que no sé que ejemplo ponerles, con patillas C0 y C1 o con patillas C7 y C6, con o sin force_sw, etcétera. Me gustaría seguir con C7 y C6 por lo que pondré ese ejemplo de código... en este sin el force_sw no recibe nada y como decía necesito que sea por hardware para que funcione la interrupción RDA.

Código: [Seleccionar]
#include <18F4550.h>
#fuses HSPLL, MCLR, PUT, BROWNOUT, BORV43, NOWDT, NOPROTECT, NOLVP
#fuses NODEBUG, USBDIV, PLL1, CPUDIV1, VREGEN, CCP2B3

#use delay (clock=48000000)

int i;
#include   <lcd.c>                              //Incluye las rutinas de manejo del LCD
#include   <GPS28500.h>                //Incluye funciones de manejo del termómetro IR 28040

#use fast_io(A)
#use fast_io(D)

int8 a=0,j=0;
int8 h0=0,h1=0,m0=0,m1=0,s0=0,s1=0,d0=0;

#INT_RDA
void rda_handler(void)
   {                                            // Interrupción recepción serie USART
   j++;
   }

#INT_TIMER1
void TIMER1()
   {
   a++;
   }

void main ()
   {
   lcd_init();
   
   ENABLE_INTERRUPTS(INT_RDA);
   
   SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_8);
   ENABLE_INTERRUPTS(INT_TIMER1);
   ENABLE_INTERRUPTS(GLOBAL);
   
   while (TRUE)
      {
      RxGGA();                                  //Lee las tramas GGA y RMC del GPS
      GPS_Time();                               //Obtiene la hora de la trama GGA
     
      h1=GPS_Buffer[0];
      h0=GPS_Buffer[1];
      m1=GPS_Buffer[2];
      m0=GPS_Buffer[3];
      s1=GPS_Buffer[4];
      s0=GPS_Buffer[5];                         //Memoriza hora en variables


      if (a>=5)
         {
         a=0;
         d0++;
         if (d0>9)
            {
            d0=0;
            }
         }
         
      lcd_gotoxy(1,1);
      printf(lcd_putc,"%1x%1x:%1x%1x:%1x%1x,%u; %u",h1,h0,m1,m0,s1,s0,d0,j);
      }
   }

La librería del GPS es igual que la inicial pero sin el force_sw en e #use rs232 y cambiando las patillas de C0 a C7 y C6. Realmente C6 no hace falta ya que solo recibimos del módulo GPS).

También he probado quitando todo el código del GPS que hay en el main, por si esa espera de las comunicaciones rs232 no le dejara hacer la interrupción RDA, pero nada... sigue si dar muestras de vida la interrupción RDA.

He estado viendo también las interrupciones por una entrada externa pero digo yo que si hay una interrupción específica para lo que quiero porque voy a andar con experimentos? Aunque si no hay más remedio...

... sigo en ello, gracias anticipadas por cualquier aportación.


Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #9 en: 08 de Septiembre de 2010, 18:53:42 »
Poco es lo que puedo aportar.

La interrupción por puerto serie sólo va a funcionar utilizando RS232 por hardware.

Otra cosa es que deberías borrar los flags de las interrupciones antes de salir de las mismas. Digo, cuando entras en la del timer1, antes de que se termine tu función deberías borrar el bit que indica que hubo una interrupción del timer, porque sino estarás entrando constantemente en dicha función. Tal vez sea ese el motivo por el cual el LCD queda en blanco

De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado abarth

  • PIC10
  • *
  • Mensajes: 6
Re: PIC + GPS + LCD: problema rs232 con un timer
« Respuesta #10 en: 11 de Septiembre de 2010, 08:39:59 »
Bueno, gracias a Angel y a MLO por las respuestas.

Al final he conseguido hacer funcionar la interrupción (problemas en los fuses más que nada), manejándola más o menos a mi antojo y llegando a la conclusión de que esta forma de conectar con el GPS, en la que el PIC debe estar continuamente pendiente de la entrada rs232 comparando las cabeceras de las transmisiones, no me sirve o me deja el PIC bastante limitado para las otras varias tareas que pretendo que realice.

Creo que será mejor irse a un GPS ya microcontrolado, al que se le puedan hacer consultas en el momento que quieras... respondiendo este con el dato solicitado, dejando libre el USART del PIC para otras aplicaciones.