我正在编写一个C ++程序来从通过串口连接的设备获取和解析GNSS数据。建立连接后,我得到的只是一些乱码而不是预期的NMEA句子。有谁知道我的错误在哪里? 当我使用PuTTY输出数据时,有部分乱码和部分好的NMEA句子。
我的主要代码:
#include <iostream>
#include "Serial.h"
int main()
{
Serial serial;
unsigned char buffer[256];
std::string port = "COM19";
const char *portaddress=port.data();
std::cout<<serial.Open(portaddress,9600);
//unsigned char *buffer;
int read;
int readlast;
read=serial.Read(buffer, 255);
unsigned char line[256];//=new int[];
int counter=0;
while(1)
{
while(read==0)
{
read=serial.Read(buffer, 255);
}
counter=0;
line[counter]=read;
counter++;
while(read!=0)
{
//std::cout<<read;
readlast=read;
read=serial.Read(buffer, 255);
line[counter]=read;
counter++;
}
for(int i=0;i<sizeof(line)/sizeof(*line);i++)
{
std::cout<<line[i];
}
break;
}
return 0;
}
serial.Read():
int Serial::Read(unsigned char* buffer, int length) {
WaitForSingleObject(m_Mutex, INFINITE);
DWORD bytesRead = 0;
ReadFile(m_SerialHandle, buffer, length, NULL, &m_Overlapped);
GetOverlappedResult(m_SerialHandle, &m_Overlapped, &bytesRead, 1);
ReleaseMutex(m_Mutex);
return (int)bytesRead;
}
输出:
0 <@ `▀F ÉòG $òG Ç@ $ ¶â.X■i >uñv Iuñvÿ1V fm~wç }w $ ( ¶â.ÿ■i >uñv Iuñv├ÿ1V fm~wç }w $ ä■i þÆAö■i «kªv, Ç@ ÓêA ¼■i àtªv©?½vý■i óiª ssÑvjsÑvÀÿ1VÇ@ Ç@ ÓêA
当我离开break
时,它没有变得更好。我的GNSS板的规范说输出应该是ASCII协议NMEA 0813 v4.0
。
编辑: 这是我使用HTerm.exe时的输出。有很多垃圾字节,但在两者之间你可以找到NMEA句子。设置是1个停止位,8个数据位,没有奇偶校验,9600波特(我在u-blox的u-center软件中也使用它,它就像魅力一样)。
?b<5><1><2><\0><6><\0><14>7?b<5><1><2><\0><6><\0>
<14>7?b<5><1><2><\0><6><1><15>8?b<5><1><2><\0><6><1>
<15>8?b<5><1><2><\0><6><1><15>8?b<5><1><2><\0><6><1>
<15>8?b<5><1><2><\0><6><1><15>8?b<5><1><2><\0><6><1>
<15>8?b<5><1><2><\0><6><1><15>8?b<5><1><2><\0><6><1>
<15>8?b<5><1><2><\0><6><1><15>8?b<2><20>,<\0><1><\0>
<\0><\0><4>)<\0><\0><4>)<\0><\0><4>)<\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0>??????<\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0>?8
$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E<\r><\n>
$GNTXT,01,01,02,HW UBX-M8030 00080000*60<\r><\n>
$GNTXT,01,01,02,EXT CORE 3.01 (b8bc67)*66<\r><\n>
$GNTXT,01,01,02,ROM BASE 2.01 (75331)*19<\r><\n>
$GNTXT,01,01,02,FWVER=HPG 1.11*5E<\r><\n>
$GNTXT,01,01,02,PROTVER=20.01*1B<\r><\n>
$GNTXT,01,01,02,MOD=NEO-M8P-2*7B<\r><\n>
$GNTXT,01,01,02,FIS=0xEF4015 (100111)*58<\r><\n>
$GNTXT,01,01,02,GPS;GLO;BDS*06<\r><\n>
$GNTXT,01,01,02,GNSS OTP=GPS;GLO*37<\r><\n>
$GNTXT,01,01,02,LLC=FFFFFFFF-FFFFFFED-FFFFFFFF-FFFFF79E-FFFFFF69*2E<\r><\n>
$GNTXT,01,01,02,ANTSUPERV=AC SD PDoS SR*3E<\r><\n>
$GNTXT,01,01,02,ANTSTATUS=OK*25<\r><\n>
$GNTXT,01,01,02,PF=300*4B<\r><\n>?b
<\n><6>x<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<11><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0>?<2>?b<\n><\b><28><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\n>
<\0><6><\0><\0><\0><20><\0><6><\0><\0><11><20><\0>
<\0>w??b<\n><7><24><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0>)E?b<\n><2>x<\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0>?<17><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><1><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0>?<\0><\0><\0>?<\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><1><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0>???b<\n><9><<\0><\0>?<1><\0>
<\0><\0><\0><\0><\0>@<1><\0>??<1><\0>d<\0>?<3><2><1>
<\0>???<1><\0><\n><11><\f><\r><14><15><1><\0><2>
<3>?<16>?<18>D65E?^<\0><\0><\0><\0>??<1><\0><\0><\0>
<\0><\0>%??b<\n><11><28><\0>/?w?f<\0><\0><\0>????????????<\0>
<\0><\0><\0><\0><\0><\0><\0>]Y?b<2><20>,<\0><1>
<\0><\0><\0>?*<\0><\0>?*<\0><\0>?*<\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0>??????<\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0>???b<2><21><16>
<\0><\0><\0><\0><\0><\0><\0>$@<\0><\0><17><\0><\0>
<1>?+M<29>?b<1><6>4<\0>?*<\0><\0><\0><\0><\0><\0><\0>
<\0><\0>@?C<4>&<\0><\0><\0><\0><\0><\0><\0><\0>???&<\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>?<7><\0>
<\0><15>'<2><\0>?xq<3><18>A?b<1><7>\<\0>?*<\0><\0>?<7><\n>
<18><\0><\0><11>?????<\0><\0><\0><\0><\0><\0><4><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>????????<\0>
v??<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0> N<\0><\0>??<18><1><15>'<\0>
<\0>?x!7<\0><\0><\0><\0><\0><\0><\0><\0>(??b<1>0<\b>
<\0>?*<\0><\0><\0><4><\0><\0>_^?b<1>4<\b><\0>?*<\0>
<\0><1><\0><\0><\0>`??b<1>5<\b><\0>?*<\0><\0><1><\0>
<\0><\0>a??b<1><3><16><\0>?*<\0><\0><\0>@<\0><\b><\0>
<\0><\0><\0><\f>+<\0><\0>?<28>?b<1><1><20><\0>?*<\0>
<\0>?C<4>&<\0><\0><\0><\0><\0><\0><\0><\0>???&???b<1>
<2><28><\0>?*<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0>????????<\0>v??i??b<1><4><18><\0>?*<\0>
<\0><15>'<15>'<15>'<15>'<15>'<15>'<15>'???b<1><17><20>
<\0>?*<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0>?<7><\0><\0><31>*?b<1><18>$<\0>?*<\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0>?<7><\0><\0>??<18>
<1>k??b<1> <16><\0>?*<\0><\0><\0><\0><\0><\0><\0><\0>
<17><\0>????`??b<1>#<20><\0>?*<\0><\0><11><\0><\0><\0>
<\0><\0><\0><\0>k<5><5><\0>???????b<1>$<20><\0>?*<\0>
<\0><11><\0><\0><\0><\0><\0><\0><\0>K<7><3><\0>???????b<1>!<20>
<\0>?*<\0><\0>????<\0><\0><\0><\0>?<7><\n><18><\0>
<\0><11>?Q??b<1>&<24><\0>?*<\0><\0><\0><\0><\0><\0><7>
<17><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0>y<3>?b<1>"<20><\0>?*<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>????|69<\0>@F?b<1><9><20><\0><\0><\0><\0><\0>?*<\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0>@??b<1>;(<\0><\0><\0><\0><\0>?*<\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0>?C?b<1><(<\0><\0><\0><\0><\0>?*<\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0><\0>
<\0>?n?b<1>9<\b><\0>?*<\0><\0><\0><\0><\0><\0>d?
$GNDTM,W84,,0.0,N,0.0,E,0.0,W84*71<\r><\n>
$GNRMC,,V,,,,,,,,,,N*4D<\r><\n>
$GNVTG,,,,,,,,,N*2E<\r><\n>
$GNGNS,,,,,,NN,00,99.99,,,,*7D<\r><\n>
$GNGGA,,,,,,0,00,99.99,,,,,,*56<\r><\n>
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E<\r><\n>
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E<\r><\n>
$GPGSV,1,1,00*79<\r><\n>$GLGSV,1,1,00*65<\r><\n>
$GNGLL,,,,,,V,N*7A<\r><\n>
$GNGRS,,1,,,,,,,,,,,,*7E<\r><\n>
$GNGRS,,1,,,,,,,,,,,,*7E<\r><\n>
$GNGST,,0.0000,,,,3750000,3750000,3750000*66<\r><\n>
$GNZDA,,,,,00,00*56<\r><\n>
$GNGBS,,,,,,,,*5F<\r><\n>
$GNVLW,,,,,,,,*44<\r><\n>
$PUBX,00,000011.00,0000.00000,N,00000.00000,E,0.000,NF,5303301,3750000,0.000,0.00,0.000,,99.99,99.99,99.99,0,0,0*2A<\r><\n>
$PUBX,03,00*1C<\r><\n>
$PUBX,04,000011.00,181015,11.00,1867,17D,0,0.000,21*6C<\r><\n>?b<2> `<2>?
也许设置错了?虽然我试图添加:
serialParams.DCBlength=sizeof(serialParams);
serialParams.fParity=FALSE;
serialParams.fDtrControl=0;
serialParams.fRtsControl=0;
serialParams.fOutX=TRUE;
serialParams.fInX=TRUE;
serialParams.fBinary=FALSE;
serialParams.fOutxCtsFlow=FALSE;
serialParams.fOutxDsrFlow=FALSE;
serialParams.fDsrSensitivity=FALSE;
serialParams.fErrorChar=FALSE;
serialParams.fNull=FALSE;
serialParams.fAbortOnError=FALSE;
到Serial::Open()
,它仍然输出相同的输出。也许缓冲区有问题?我仍然没有真正掌握缓冲区的概念以及它们应该存在多长时间,所以我很可能在那里犯了错误。
编辑2:
希望(和忘记)Serial::Open()
int Serial::Open(const char* port, int baudrate) {
// if connected: close current connection before opening a new one
if(m_SerialHandle != INVALID_HANDLE_VALUE) {
Close();
}
TCHAR vibroTacPort[15];
sprintf(vibroTacPort, "\\\\.\\%s", port);
// Open serial port
m_SerialHandle = CreateFile(vibroTacPort, // port // "\\\\.\\COM13"
GENERIC_READ | GENERIC_WRITE,
0,//FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING | FILE_ATTRIBUTE_TEMPORARY, // | FILE_ATTRIBUTE_NORMAL,
NULL);
// FILE_FLAG_OVERLAPPED is necessary for event-driven communication, Handle hast to be flagged for overlapped IO, otherwise Serial::Request() blocks if no event occurs (e.g. if the VibroTac device does not respond to the request)
// FILE_ATTRIBUTE_TEMPORARY, FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING increase the system performance
// Note: FILE_FLAG_WRITE_THROUGH is not be supported by all hard disks
// (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx#caching_behavior)
if(m_SerialHandle == INVALID_HANDLE_VALUE)
{
DWORD errorCode = GetLastError();
// Handle the error.
switch(errorCode) {
case ERROR_FILE_NOT_FOUND:
case ERROR_ACCESS_DENIED:
// 121 The semaphore timeout period has expired.
// 1167 The device is not connected.
// fall through and do nothing for now
;
}
return (errorCode);
}
// Do some basic settings
DCB serialParams = { 0 };
serialParams.DCBlength = sizeof(serialParams);
if (!GetCommState(m_SerialHandle, &serialParams)) {
Close();
return ERROR_OPEN_FAILED;
};
serialParams.BaudRate = CBR_9600;//baudrate;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
/*serialParams.DCBlength=sizeof(serialParams);
serialParams.fParity=FALSE;
serialParams.fDtrControl=0;
serialParams.fRtsControl=0;
serialParams.fOutX=TRUE;
serialParams.fInX=TRUE;
serialParams.fBinary=FALSE;
serialParams.fOutxCtsFlow=FALSE;
serialParams.fOutxDsrFlow=FALSE;
serialParams.fDsrSensitivity=FALSE;
serialParams.fErrorChar=FALSE;
serialParams.fNull=FALSE;
serialParams.fAbortOnError=FALSE;*/
if (!SetCommState(m_SerialHandle, &serialParams)) {
Close();
return ERROR_OPEN_FAILED;
}
// Set timeouts
COMMTIMEOUTS timeout = { 1 };
timeout.ReadIntervalTimeout = 100; //100 // 0 = "not used", the maximum time allowed to elapse before the arrival of the next byte on the communications line, in milliseconds.
timeout.ReadTotalTimeoutConstant = 0; // A constant used to calculate the total time-out period for read operations, in milliseconds. For each read operation, this value is added to the product of the ReadTotalTimeoutMultiplier member and the requested number of bytes.
timeout.ReadTotalTimeoutMultiplier = 80;//20 // The multiplier used to calculate the total time-out period for read operations, in milliseconds. For each read operation, this value is multiplied by the requested number of bytes to be read.
timeout.WriteTotalTimeoutConstant = 1;
timeout.WriteTotalTimeoutMultiplier = 1;
if (!SetCommTimeouts(m_SerialHandle, &timeout)) {
Close();
return ERROR_OPEN_FAILED;
}
// Set event mask
// Events:
// EV_RXCHAR 0x0001 A character was received and placed in the input buffer.
// EV_ERR 0x0080 A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
DWORD dwEvtMask = EV_RXCHAR | EV_ERR;
if(!SetCommMask(m_SerialHandle, dwEvtMask)) {
Close();
return ERROR_OPEN_FAILED;
};
// initialize m_Overlapped with 0
memset(&m_Overlapped, 0, sizeof(m_Overlapped));
// Create an event object for use by WaitCommEvent.
m_Overlapped.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
m_Overlapped.Internal = 0;
m_Overlapped.InternalHigh = 0;
m_Overlapped.Offset = 0;
m_Overlapped.OffsetHigh = 0;
return 0;
}
编辑3:
我想也许最好一次只读一个字节,直到我到达$
字符,然后是\n
字符,以确定哪些部分对我有用。有人可以解释我如何使用Serial::Open()
中创建的处理程序读取单个字节?如果我使用前一种方式并限制length
又名"NumberOfBytesToRead"
,我如何测试我是否到达相关部分?
答案 0 :(得分:0)
好吧,经过大量的试验和错误,以及几个小时的吸烟,我找到了一个至少在我的情况下有效的答案:
我这样改变了main.cpp
:
#include <iostream>
#include "Serial.h"
#include "GPSInfo.h"
#include "NMEAParser.h"
int main()
{
Serial serial;
unsigned char buffer[256];
std::string port = "COM19";
const char *portaddress=port.data();
serial.Open(portaddress,9600);
std::string read;
read=serial.Read(buffer);
while(1)
{
read=serial.Read(buffer);
std::cout<<read;
}
return 0;
}
和Serial::Read()
是这样的:
std::string Serial::Read(unsigned char* buffer) {
WaitForSingleObject(m_Mutex, INFINITE);
DWORD bytesRead = 0;
DWORD nNumberOfBytesToRead=1; // new
char a=0;
char *ptr=&a;
char last=0;
std::string output="";
ReadFile(m_SerialHandle, ptr, nNumberOfBytesToRead, NULL, &m_Overlapped);
GetOverlappedResult(m_SerialHandle, &m_Overlapped, &bytesRead, 1);
if(a=='$')
{
last=a;
ReadFile(m_SerialHandle, ptr, nNumberOfBytesToRead, NULL, &m_Overlapped);
if(a=='G'||a=='P'||a=='S')
{
output+=last;
output+=a;
while (a!='\n')
{
ReadFile(m_SerialHandle, ptr, nNumberOfBytesToRead, NULL, &m_Overlapped);
output+=a;
}
}
}
ReleaseMutex(m_Mutex);
return output;
}
现在我有以下输出:
$GNDTM,W84,,0.0,N,0.0,E,0.0,W84*71
$GNRMC,095639.00,A,4804.88405,N,01116.55021,E,0.415,,181016,,,A*6C
$GNVTG,,T,,M,0.415,N,0.769,K,A*35
$GPGSV,4,1,14,01,12,263,,07,00,284,,08,57,301,18,10,66,091,24*7B
$GPGSV,4,2,14,11,23,280,16,14,00,152,,15,04,026,,16,26,194,*7E
$GPGSV,4,3,14,18,37,056,13,21,11,079,,26,03,179,18,27,78,145,18*78
$GPGSV,4,4,14,30,03,310,,32,16,131,*7B
$GLGSV,3,1,09,70,43,047,15,71,57,137,33,72,17,181,17,76,09,244,*6F
$GLGSV,3,2,09,77,22,293,,78,12,347,,85,29,101,25,86,71,030,*63
$GLGSV,3,3,09,87,29,306,13*5F
$GNGLL,4804.88405,N,01116.55021,E,095639.00,A,A*7A
$GNGRS,095639.00,1,-2.7,7.0,,,,,,,,,,*7F
$GNTXT,01,01,00,txbuf alloc*61
$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E
$GNTXT,01,01,02,HW UBX-M8030 00080000*60
$GNTXT,01,01,02,EXT CORE 3.01 (b8bc67)*66
$GNTXT,01,01,02,ROM BASE 2.01 (75331)*19
$GNTXT,01,01,02,FWVER=HPG 1.11*5E
$GNTXT,01,01,02,PROTVER=20.01*1B
这正是我想要的。 (有时候仍然有垃圾,但我认为这不会影响我的解析。)
感谢您的所有评论和答案,它帮助了很多。