gpt4 book ai didi

c++ - Raspberry Pi C++ 从 Adafruit 的终极 GPS 模块读取 NMEA 语句

转载 作者:太空宇宙 更新时间:2023-11-04 02:55:24 25 4
gpt4 key购买 nike

我正在尝试从 Adafruit 的 Ultimate GPS 模块中读取 GPS NMEA 语句。我在树莓派上使用 C++ 读取模块的串口连接

这是我的阅读功能:

int Linuxutils::readFromSerialPort(int fd, int bufferSize) {

/*
Reading data from a port is a little trickier. When you operate the port in raw data mode,
each read(2) system call will return however many characters are actually available in the
serial input buffers. If no characters are available, the call will block (wait) until
characters come in, an interval timer expires, or an error occurs. The read function can be
made to return immediately by doing the following:
fcntl(fd, F_SETFL, FNDELAY);
The NDELAY option causes the read function to return 0 if no characters are available on the port.
*/

// Check the file descriptor
if ( !checkFileDecriptorIsValid(fd) ) {
fprintf(stderr, "Could not read from serial port - it is not a valid file descriptor!\n");
return -1;
}

// Now, let's wait for an input from the serial port.
fcntl(fd, F_SETFL, 0); // block until data comes in

// Now read the data
int absoluteMax = bufferSize*2;
char *buffer = (char*) malloc(sizeof(char) * bufferSize); // allocate buffer.
int rcount = 0;
int length = 0;

// Read in each newline
FILE* fdF = fdopen(fd, "r");
int ch = getc(fdF);
while ( (ch != '\n') ) { // Check for end of file or newline

// Reached end of file
if ( ch == EOF ) {
printf("ERROR: EOF!");
continue;
}

// Expand by reallocating if necessary
if( rcount == absoluteMax ) { // time to expand ?
absoluteMax *= 2; // expand to double the current size of anything similar.
rcount = 0; // Re-init count
buffer = (char*)realloc(buffer, absoluteMax); // Re-allocate memory.
}

// Read from stream
ch = getc(fdF);

// Stuff in buffer
buffer[length] = ch;

// Increment counters
length++;
rcount++;

}

// Don't care if we return 0 chars read
if ( rcount == 0 ) {
return 0;
}

// Stick
buffer[rcount] = '\0';

// Print results
printf("Received ( %d bytes ): %s\n", rcount,buffer);

// Return bytes read
return rcount;

}

所以我得到的句子如下所示,问题是我得到了一个完整句子的这些“重复”部分,如下所示:

Received ( 15 bytes ): M,-31.4,M,,*61

这里是完整的东西:

Received ( 72 bytes ): GPGGA,182452.000,4456.2019,N,09337.0243,W,1,8,1.19,292.6,M,-31.4,M,,*61

Received ( 56 bytes ): GPGSA,A,3,17,07,28,26,08,11,01,09,,,,,1.49,1.19,0.91*00

Received ( 15 bytes ): M,-31.4,M,,*61

Received ( 72 bytes ): GPGGA,182453.000,4456.2019,N,09337.0242,W,1,8,1.19,292.6,M,-31.4,M,,*61

Received ( 56 bytes ): GPGSA,A,3,17,07,28,26,08,11,01,09,,,,,1.49,1.19,0.91*00

Received ( 15 bytes ): M,-31.4,M,,*61

Received ( 72 bytes ): GPGGA,182456.000,4456.2022,N,09337.0241,W,1,8,1.21,292.6,M,-31.4,M,,*64

Received ( 56 bytes ): GPGSA,A,3,17,07,28,26,08,11,01,09,,,,,2.45,1.21,2.13*0C

Received ( 70 bytes ): GPRMC,182456.000,A,4456.2022,N,09337.0241,W,0.40,183.74,110813,,,A*7F

Received ( 37 bytes ): GPVTG,183.74,T,,M,0.40,N,0.73,K,A*34

Received ( 70 bytes ): GPRMC,182453.000,A,4456.2019,N,09337.0242,W,0.29,183.74,110813,,,A*7E

Received ( 37 bytes ): GPVTG,183.74,T,,M,0.29,N,0.55,K,A*3F

Received ( 32 bytes ): 242,W,0.29,183.74,110813,,,A*7E

Received ( 70 bytes ): GPRMC,182452.000,A,4456.2019,N,09337.0243,W,0.33,183.74,110813,,,A*75

为什么我会收到重复的句子,我该如何解决?我尝试刷新串行端口缓冲区,但事情变得非常难看!谢谢。

最佳答案

我不确定我是否理解您的确切问题。尽管该函数存在一些问题,但可能会解释各种错误。

线条

int absoluteMax = bufferSize*2;
char *buffer = (char*) malloc(sizeof(char) * bufferSize); // allocate buffer.

好像错了。您将通过将读取的字符数与 absoluteMax 进行比较来决定何时增加缓冲区,因此这需要与分配的缓冲区大小相匹配。在重新分配之前,您目前正在超出已分配内存的末尾进行写入。这会导致未定义的行为。如果你幸运的话,你的应用程序会崩溃,如果你不走运,事情似乎可以正常工作,但你会丢失你读取的后半部分数据,因为只有写入你拥有的内存的数据会被移动 realloc(如果它重新定位您的堆单元)。

此外,您不应从 malloc(或 realloc)强制转换返回值,并且可以依赖 sizeof(char) 为 1。

您丢失了读取的第一个字符(在 while 循环之前读取的字符)。这是故意的吗?

当你重新分配buffer时,你不应该重置rcount。这会导致与上面相同的错误,您将在再次重新分配之前编写超出 buffer 末尾的内容。同样,这样做的效果是不确定的,但可能包括丢失部分输出。

与您当前关注的错误无关但同样值得注意的是您泄漏了 bufferfdF。在退出该函数之前,您应该分别freefclose 它们。

以下(未经测试的)版本应该可以解决这些问题

int Linuxutils::readFromSerialPort(int fd, int bufferSize)
{
if ( !checkFileDecriptorIsValid(fd) ) {
fprintf(stderr, "Could not read from serial port - it is not a valid file descriptor!\n");
return -1;
}

fcntl(fd, F_SETFL, 0); // block until data comes in
int absoluteMax = bufferSize;
char *buffer = malloc(bufferSize);
int rcount = 0;
int length = 0;

// Read in each newline
FILE* fdF = fdopen(fd, "r");
int ch = getc(fdF);
for (;;) {
int ch = getc(fdF);
if (ch == '\n') {
break;
}
if (ch == EOF) { // Reached end of file
printf("ERROR: EOF!\n");
break;
}
if (length+1 >= absoluteMax) {
absoluteMax *= 2;
char* tmp = realloc(buffer, absoluteMax);
if (tmp == NULL) {
printf("ERROR: OOM\n");
goto cleanup;
}
buffer = tmp;
}
buffer[length++] = ch;
}

if (length == 0) {
return 0;
}
buffer[length] = '\0';

// Print results
printf("Received ( %d bytes ): %s\n", rcount,buffer);

cleanup:
free(buffer);
fclose(fdH);
return length;
}

关于c++ - Raspberry Pi C++ 从 Adafruit 的终极 GPS 模块读取 NMEA 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18175353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com