问题
Hy everybody!
I wrote a small gps application in simple C++, what switch the protocoll, send command to the gps chip...etc. The write to the GPS port is working good. But when I try to read the port (for check the accepted commands) I receive a lot of stupid characters. Normally an NMEA output message is something like this:
$GPGLL,4916.45,N,12311.12,W,225444,A
And I received similar:
1C0CFC14
I dont know whats wrong... This part of my code is the next:
LPCVOID buffer[100];
ReadFile(hSerial, buffer, 100, 0, 0);
Or an other for log some data:
LPCVOID buffer[100];
ReadFile(hSerial, buffer, 100, 0, 0);
ofstream log ("log.txt");
log << buffer;
log.close();
Of course the Hserial is declared before and its working good for write. When Im declared the HANDLE I opened the hSerial file to read and write too. The targeted platform is Windows Mobile 5.0 and 6.0. Whats wrong? Many thanks for the help!
回答1:
Reading data from a GPS port, or any other data from a port, is not exactly a simple matter.
You need to ensure that there is some data waiting and that the COM port is clear of any previous errors before trying to read. Then, if the read is successful then you need to ensure that the data is properly terminated and comprises a complete NMEA sentence. Sometimes you may gat the beginning of the next NMEA sentence, or even several back to back in one read, so you have to deal with that.
Let's leave all that for another day, and focus on the read itself.
The 4th parameter of ReadFile should be a pointer to a DWORD which will store the number of bytes actually read. You should be using this, to make sure you got some real data. You should also be checking the return value for errors.
Here is how I do it, after checking that there is actually some data waiting to be read.
/**
Read data from port
@param[in] buffer pointer to location to store data
@param[in] limit maximum number of bytes to read
@return 0 if error
*/
int cSerial::ReadData( void *buffer, int limit )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( ::GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
It seems all very complicated, however everything in the above code is proved necessary. Without it, your app may run for a while, but at some time it will either hang or give you garbles. You can leave some of these checks out, but then you will have to spend many hours trying to debug what went wrong with your app - like I did when developing this code.
来源:https://stackoverflow.com/questions/10020112/receive-nmea0183-data-from-com-port-c