Recibiendo correctamente los caracteres nmea del GPS A2200-A

0

He estado trabajando en este proyecto por un tiempo, tratando de recibir los caracteres de mi GPS y luego mostrarlos en una pantalla LCD de 16x2. Estoy utilizando una interrupción en mi pin UART RX que permite al programa ingresar a la rutina de servicio de interrupción cuando se detecta un carácter que está funcionando.

En la rutina de servicio de interrupción, los datos NMEA luego se extraen y almacenan en una matriz de 80 caracteres y luego se dividen de nuevo en matrices más pequeñas para extraer los datos individuales que quiero mostrar. Sin embargo, cuando voy a mostrar estos caracteres, no veo nada.

La parte LCD del programa está funcionando perfectamente y puedo ver en mi osciloscopio que los caracteres están siendo transmitidos por el GPS, por lo que el problema podría ser que no esté almacenando esta información correctamente y que haya configurado las tasas de bits correctamente.

El microcontrolador que estoy usando es el PIC32mx795f512h, si alguien pudiera saber cuál sería mi problema, cualquier ayuda sería muy apreciada.

A continuación se encuentra mi rutina principal y de servicio de interrupción

int32_t main(void)
{
#ifndef PIC32_STARTER_KIT
    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    InitApp();             //initialise ports & interrupts
    intLCD();              //initialise LCD
    clrLCD();
    putsLCD("Initialising \n \t TCAS");


    // configure for multi-vectored mode
 INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

//UART1 enable for own gps
 UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
 UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
 UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
 UARTSetDataRate(UART1, GetPeripheralClock(), 4800);
 UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

 // Configure UART1 RX Interrupt
 INTEnable(INT_SOURCE_UART_RX(UART1), INT_ENABLED);
 INTSetVectorPriority(INT_VECTOR_UART(UART1), INT_PRIORITY_LEVEL_2);
 INTSetVectorSubPriority(INT_VECTOR_UART(UART1), INT_SUB_PRIORITY_LEVEL_0);


 //UART2 enable for surrounding


 PORTSetPinsDigitalOut(IOPORT_F, BIT_5);                    //data transmitter
 PORTSetPinsDigitalIn(IOPORT_F, BIT_4);                     //data receiver


 // enable interrupts
 INTEnableInterrupts();

 //allow uart >300ms to initialise
 Delayms(5000);

 gpsINITIALISE();        //initialise GPS to receive data >100ms

 //main loop
 int check = 0;
 while(1)     //wait in here for uart interrupt
 {
        ValidMsg = NotTrue;     //clear valid message variable
    if(check == 0)
    {
                    putsLCD("Resend \n \t message");
        sendMessages(); //send for gga message
        check = 1;
    }
          if(ValidMsg = True) //check to see if data is valid in main string
          {
               putsLCD("Message \n \t Valid");
               DisableIntU1RX;   //dissable interrupts on uart 1
               createString();   //create character string to transmit to nearby aircraft
               EnableIntU2RX;    //enable interrupts on UART2
               Delayms(10000);   //wait for data to be received from nearby aircraft
               DisableIntU2RX;   //dissable interrupts on uart 2
               GPStest();        //display the individual strings

          }
        if (ValidMsg = NotTrue) //check to see is not valid
          {
             putsLCD("Message1 \n \t Invalid");
             for(s=0; s<80; s++)        //clear received data string
                  {
                      GGA[s]=0;
                   }
             sendMessages(); //resend for gga message
           }
    }
}






// U1RX interrupt, majority of GPS relies within
void __ISR(_UART_1_VECTOR, ipl6) _U1RXInterrupt(void)
{
    int parse=0;    // string counter
if(U1STAbits.OERR == 1)
    U1STAbits.OERR = 0;

if(U1STAbits.URXDA) //check if data is ready to be read
    {
        c = getcUART1();
        while(UARTReceivedDataIsAvailable(UART1)); //check to see if data is available
        if(c == '$') //c == $, hex=0x0024
        {
            count = 0;
        }
        if(count < 6)
        {
            dataTest[count] = c;
            count++;
        }
        else if(count > 5 && count < 80)
        {
            if(dataTest[4]=='G')     //test data string
                               {
                         GGA[count]=c;
                                     ValidMsg = True;    //data is valid
                               }
            else  //error
                                ValidMsg = NotTrue;    //data is valid
                count++;
                                PORTToggleBits(IOPORT_B, BIT_2);
        }
    }

    //extract data into individual strings
            x=0;
    for(parse=1;parse<80;parse++)
    {

        if ((parse >=1) & (parse <6)) //Message Type
        {
            command[parse-1] = GGA[parse];
        }
        else if ((parse >6) & (parse < 17)) //Time
        {
            time[x] = GGA[parse];
            x++;
            if (parse == 16)
                x=0;
        }
        else if ((parse > 17) & (parse < 27)) //Latitude
        {
            lat[x] = GGA[parse];
            x++;
            if (parse == 26)
                x=0;
        }
        else if (parse == 28) //Latitude Dir
            latDir = GGA[parse];
        else if ((parse > 29) & (parse < 40)) //Longitude
        {
            lon[x] = GGA[parse];
            x++;

            if (parse == 39)
                x=0;
        }
        else if (parse == 41) //Longitude Dir
            lonDir = GGA[parse];
        else if (parse == 43) //Fix Quality

            fixQ = GGA[parse];
        else if ((parse > 51) & (parse < 55)) //altitude
        {
            altitude[x] = GGA[parse];
            x++;
            if(parse == 54)
            x=0;
        }
    }
    INTClearFlag(INT_SOURCE_UART_RX(UART1));         // Clear the RX interrupt Flag
} 
    
pregunta brook

1 respuesta

1

Una buena 'regla de oro' es hacer el menor procesamiento posible dentro de las rutinas de servicio de interrupción (ISR). Por lo general, es mucho más difícil de depurar el código dentro de una rutina de servicio de interrupción que el código ordinario.

Quitaría toda la decodificación del ISR y la pondría en main, o en una función llamada por main.

El formato de mensaje NMEA termina cada mensaje con un retorno de carro (0x0D, o '\ r') y una línea feed (0x0A o '\ n'). Así que podría buscarlos dentro del ISR y establecer una marca para indicar que se ha encontrado un mensaje completo. Tan fácil sería comprobar el carácter más reciente puesto en el búfer.

En main() , solo realizaría el procesamiento cuando llega un mensaje completo, señalado por el avance de línea.

No es necesario realizar ningún procesamiento en el mensaje NMEA mientras se realiza la prueba. Podrías imprimirlo en la pantalla LCD.

Es bastante factible que el código simplemente "engulle" el mensaje NME en algún lugar. En mi humilde opinión, el código es demasiado desordenado debido al formato en este sitio, para realizar una depuración al leerlo.

Dependiendo de la placa de desarrollo PIC32 que tenga, imprimiría el texto del mensaje NMEA en algo más simple que el LCD para dar una confirmación independiente de su contenido. Para ayudar a depurar esto, si no tiene un depurador, o una forma de sacar datos, invertiría en un USB-UART barato y utilizaría una PC para imprimirlo.

    
respondido por el gbulmer

Lea otras preguntas en las etiquetas