Procesar y almacenar datos GPS en MCU

0

Actualmente estoy trabajando en un módulo GPS de Quectel (L70). Intento conectarlo a la MCU TM4C a través de UART1 para consultar alguna posición, luego almacenarlo en la memoria de la MCU y luego enviar esa información al UART2 conectado a la computadora para poder verla en Putty o TeraTerm. Estoy trabajando con CCS6 de TI.

Tengo algunas dificultades para implementar esto. Las especificaciones del módulo GPS son aquí .

En mi entendimiento, se supone que debo inicializar el puerto UART1 de MCU, luego enviar un comando printf o put a UART incluyendo el comando PMTK o NMEA como printf("$PMTK010,001*2E<CR><LF>") , luego el módulo debe responder en el otro cable con algo como $GPRMC,013732.000,A,3150.7238,N,11711.7278,E,0.00,0.00,220413,,,A*68<CR><LF> . ¿La MCU recibe automáticamente estos datos y los almacena en la memoria? Luego necesito copiar esos datos y enviarlos a UART2 con un printf a mi computadora.

¿Estoy en lo correcto?

En el Explorador de recursos de TI de CCS6, descubrí este código UART como ejemplo. ¿Qué debo adaptar?

//*****************************************************************************
//
// uart_echo.c - Example for reading data from and writing data to the UART in
//               an interrupt driven fashion.
//
// Copyright (c) 2012-2016 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.1.3.156 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>UART Echo (uart_echo)</h1>
//!
//! This example application utilizes the UART to echo text.  The first UART
//! (connected to the USB debug virtual serial port on the evaluation board)
//! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
//! the UART are transmitted back to the UART.
//
//*****************************************************************************

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    uint32_t ui32Status;

    //
    // Get the interrrupt status.
    //
    ui32Status = ROM_UARTIntStatus(UART0_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    ROM_UARTIntClear(UART0_BASE, ui32Status);

    //
    // Loop while there are characters in the receive FIFO.
    //
    while(ROM_UARTCharsAvail(UART0_BASE))
    {
        //
        // Read the next character from the UART and write it back to the UART.
        //
        ROM_UARTCharPutNonBlocking(UART0_BASE,
                                   ROM_UARTCharGetNonBlocking(UART0_BASE));

        //
        // Blink the LED to show a character transfer is occuring.
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

        //
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        //
        SysCtlDelay(SysCtlClockGet() / (1000 * 3));

        //
        // Turn off the LED
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

    }
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
{
    //
    // Loop while there are more characters to send.
    //
    while(ui32Count--)
    {
        //
        // Write the next character to the UART.
        //
        ROM_UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
    }
}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPUEnable();
    ROM_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF2).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    //
    // Enable the peripherals used by this example.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable processor interrupts.
    //
    ROM_IntMasterEnable();

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    ROM_IntEnable(INT_UART0);
    ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    //
    // Prompt for text to be entered.
    //
    UARTSend((uint8_t *)"3[2JEnter text: ", 16);

    //
    // Loop forever echoing data through the UART.
    //
    while(1)
    {
    }
}

[Dado que esta pregunta está relacionada con el software integrado en MCU, no estoy seguro de que esta pregunta deba publicarse en EE o en el intercambio de pila de software. Por favor, siéntase libre de mover mi pregunta al sitio correcto si es necesario.]

    
pregunta chris

2 respuestas

1

Respuesta actualizada basada en comentarios con el OP. Así que esto será un poco general ya que no estoy realmente familiarizado con esta familia de MCU.

Para obtener la longitud, la latitud y el tiempo, la única sentencia NMEA necesaria es la GPRMC. Así que primero debes capturar este en el ISR y almacenarlo en un búfer.

Todas las oraciones comienzan con un $ , y luego aparece la identificación del mensaje, en este caso GPRMC , la secuencia termina con \r\n .

#include<string.h>uint8_ts_buffer[200];//sentencebuffertosaveGPRMCdatavolatileuint8_tcntr=0;//bufferindexvolatileuint8_tgprmc=0;//flagtoindicateGPRMCsentenceuint8_trdy=0;//flagtoindicateifthes_bufferisreadytobeprocessedvoidUARTIntHandler(void){uint32_tui32Status;uint8_t_char;//tempvariabletoreadnextbyteuint8_tmsg_id[6];//buffertosavemsgID,whichwillbe5byteslonguint8_tid_cntr=6;//bufferindexui32Status=ROM_UARTIntStatus(UART1_BASE,true);//Gettheinterrruptstatus.ROM_UARTIntClear(UART1_BASE,ui32Status);//Cleartheassertedinterrupts.//WhiletherearecharactersinthereceiveFIFO.while(ROM_UARTCharsAvail(UART1_BASE)){_char=ROM_UARTCharGetNonBlocking(UART1_BASE);if(gprmc){//collectsentencedataif(_char=='\r'){//until'\r'isreadcntr=0;//thenresetbufferindexgprmc=0;//andresetGPRMCindication}else{s_buffer[cntr++]=_char;//storeGPRMCsentencedatardy=1;//bufferreadytobeprocessed}}if(id_cntr<6){//a'$'wasreceivedmsg_id[id_cntr++]=_char;//collectmsgIDif(id_cntr==5){msg_id[id_cntr]=0;//addterminatingnullif(strncmp(msg_id,"GPRMC", 5) == 0){// check for GPRMC
                    gprmc = 1;                       // indicate GPRMC sentence
                }
            }
        }

        if(_char == '$'){                            // wait for '$' to capture the msg ID
            id_cntr = 0;
        }

    }
}

Esto le dará una lista separada por comas que contiene los datos de GPRMC. He simulado el GPS con datos estáticos y el UART con un for cycle .

char* test = "$GPRMC,013732.000,A,3150.7238,N,11711.7278,E,0.00,0.00,220413,,,A*68\r\n$GPVTG,0.0,T,,M,0.0,N,0.1,K,A*0C\r\n$GPGGA,015540.000,3150.68378,N,11711.93139,E,1,17,0.6,0051.6,M,0.0,M,,*58\r\n$GPGSA,A,3,14,06,16,31,23,,,,,,,,1.66,1.42,0.84*0F\r\n$GPGSV,3,1,12,01,05,060,18,02,17,259,43,04,56,287,28,09,08,277,28*77\r\n$GPGSV,3,2,12,10,34,195,46,13,08,125,45,17,67,014,,20,32,048,24*74\r\n$GPGSV,3,3,12,23,13,094,48,24,04,292,24,28,49,178,46,32,06,037,22*7D\r\n$GPGLL,3110.2908,N,12123.2348,E,041139.000,A,A*59\r\n$GPRMC,015511.000,A,3152.7238,N,11720.7278,E,0.00,0.00,220413,,,A*69\r\n";

Estalistasepuedeprocesarfácilmente,ylalongitud,lalatitudyeltiemposeguardanenlaEEPROM.EnelTivaTM4Cserealizaalgoasícomo esto . La EEPROM tiene solo 2 KB, por lo que tendrá que encontrar una manera de almacenar los datos de manera eficiente para no quedarse sin espacio.

Esto es para el análisis y almacenamiento de datos.

Para enviar los datos a una PC, debe escuchar en UART2 un comando que, si se recibe, puede leer los datos de la EEPROM (formatearlos si ha realizado algunas modificaciones para almacenarlos de manera eficiente) y utilizar la función de envío. para transmitir los datos.

    
respondido por el Bence Kaulics
0

No estoy familiarizado con esa CPU / entorno, por lo que no puedo comentar sobre detalles específicos del código.

Si lees la documentación del módulo GPS, al comienzo de la sección 2 verás que, de manera predeterminada, se emiten todos los mensajes NMEA, de modo que, a menos que quieras cambiar, no deberías enviar ningún comando.

Así que todo lo que necesitas hacer es:

  • Inicializa ambos uarts. (9600 baudios para el GPS, como desee para la conexión a la PC)
  • Configura la rutina de interrupción UART0 para reenviar todo lo que recibe a UART1.

El código de muestra que publicaste actualmente utiliza 115200 baudios y la rutina de interrupción está devolviendo los datos a uart0, cambiarlo para enviarlo a uart1 debería ser tan simple como cambiar un 0 por un 1.

El código de muestra también tiene una pausa y establece los LED, es probable que desee eliminar esos bits.

    
respondido por el Andrew

Lea otras preguntas en las etiquetas