Не читаемый ввод с последовательного устройства GNSS — но не с PuTTY

Я пишу программу на 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-center от u-blox, и там оно работает как чудо).

?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 char, чтобы определить, какие части полезны для меня. Может кто-нибудь объяснить, как я могу прочитать один байт, используя обработчик, созданный в Serial::Open()? Если я буду использовать первый способ и ограничить length ака "NumberOfBytesToRead"Как я могу проверить, достиг ли я соответствующей части?

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

это именно то, что я хочу. (Иногда мусор все еще существует, но я не думаю, что это повлияет на мой анализ.)

Спасибо за все ваши комментарии и ответы, это очень помогло.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]