如何通过带有c的串行端口从带有NMEA协议的GPS模块中获取数据

时间:2019-06-11 19:24:54

标签: c serial-port gps nmea

我需要通过串行端口从采用NMEA协议的GPS模块获取数据,输入看起来像这样:

  

$ GPRMC,190335.389,V,3754.931,N,08002.496,W,33.6,0.59,110619,,E * 47   $ GPGGA,190336.389,3754.931,N,08002.496,W,0,00 ,,, M ,, M ,, * 52   $ GPGLL,3754.931,N,08002.496,W,190337.389,V * 33   $ GPVTG,0.59,T ,, M,33.6,N,62.2,K * 5C   $ GPRMC,190339.389,V,3754.932,N,08002.494,W,11.9,0.62,110619,,E * 4D   $ GPGGA,190340.389,3754.932,N,08002.494,W,0,00 ,,, M ,, M ,, * 52   $ GPGLL,3754.932,N,08002.494,W,190341.389,V * 33

问题是,我只需要以GPRMC开头的行。问题是数据将异步传输,例如首先到达一行的前半部分,然后是另一半以及其他一些行,依此类推。现在如何才能逐行获取输入,而仅以GPRMC开头。输入不断,我需要实时获取正确的行。我如何用C做到这一点?

我真的不知道如何从串行端口读取,我尝试了一些操作,但是由于输入即将异步,所以无法获得正确的行。哦,还有一件事,一行的最大长度是83。

这是我尝试过的一些代码,我知道这很糟糕

int a = 0;
int test = 0;
int gprmc_find(char* gps)
{
    while(a < strlen(gps))
    {
        if(gps[a] =='$' && gps[a+1] == 'G' && gps[a+2] == 'P' && gps[a+3] == 'R' )
        {
            test = 1;
            break;
        }
        else
        {
            test = 0;
        }
        a++;
        return test;
    }
}
int main()
{

DWORD  accessdirection =GENERIC_READ | GENERIC_WRITE;
HANDLE hSerial = CreateFile("COM4",
                            accessdirection,
                            0,
                            0,
                            OPEN_EXISTING,
                            0,
                            0);
if (hSerial == INVALID_HANDLE_VALUE) {
    printf("Invalid\n");
}

DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
     printf("could not get the state of the comport\n");
}
dcbSerialParams.BaudRate=9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams)){
     printf("Error\n");
}
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts)){
    printf("handle error1");
}
    char buf[83] = {0};
    while(1)
    {


        DWORD dwBytesRead = 0;

       //CloseHandle(hSerial);

        if(!ReadFile(hSerial, buf, 82, &dwBytesRead, NULL)){
            printf("handle error");
        }
        printf(" %d \n", test);
        if(gprmc_find(buf) == 1)
        {
            printf(buf);  
        }
        memset(buf, 0, 83);
        delay(1);
    }
    return 0;

}

1 个答案:

答案 0 :(得分:0)

GPS NMEA 0183是基于文本的协议,可以使用与平台无关的C语言标准库进行处理。
已经开发了许多库和解析器,您无需重新开发就可以使用它们。

例如,您可以在StackOverflow网站上找到此文章:
NMEA library - nmeaINFO empty / NMEA Library
C Gps nmea parser from linux serial port does not parse the last line of the read buffer
Parsing code for GPS NMEA string

其他站点:
MULTI-PLATFORM SERIAL INTERFACING USING BOOST: A GPS SENSOR AND OPENDDS - PART I / PART II

这些是解析器,用于解析读取的数据的库。
jacketizer/libnmea
kosma/minmea
MaJerle/GPS_NMEA_parser

在上述库中进行分析之后,您应该仅使用所需的数据。