📄 nmea.cpp
字号:
034.4,M Magnetic track made good
005.5,N Ground speed, knots
010.2,K Ground speed, Kilometers per hour
Note that, as of the 2.3 release of NMEA, there is a new field in the VTG sentence at the end just prior to the checksum. For more information on this field see here.
Receivers that don't have a magnetic deviation (variation) table built in will null out the Magnetic track made good.
$GPVTG
Track Made Good and Ground Speed.
eg1. $GPVTG,360.0,T,348.7,M,000.0,N,000.0,K*43
eg2. $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*41
054.7,T True course made good over ground, degrees
034.4,M Magnetic course made good over ground, degrees
005.5,N Ground speed, N=Knots
010.2,K Ground speed, K=Kilometers per hour
eg3. for NMEA 0183 version 3.00 active the Mode indicator field
is added at the end
$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K,A*53
A Mode indicator (A=Autonomous, D=Differential,
E=Estimated, N=Data not valid)
*/
NMEA_STATUS NMEASendGPVTG( void )
{
NMEA_VTG_DATA NmeaVTGData;
char pFieldBuffer[ MAX_NMEA_FIELD ];
char TXBufferIndex = 0;
char TransmitBuffer[ MAX_NMEA_BUFFER ];
memset( TransmitBuffer,0, MAX_NMEA_BUFFER );
memset( &NmeaVTGData, 0, sizeof( NMEA_VTG_DATA ) );
//
// Get the necessary data from the FW.
//
NMEAGetGPVTGData( &NmeaVTGData );
TXBufferIndex = 0;
//
// Add the header
//
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_START );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_GPVTG );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// True heading
//
ftoa( NmeaVTGData.TrueHeading, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_TRUE_HEADING );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Mag heading
//
ftoa( NmeaVTGData.MagHeading, pFieldBuffer );
// NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_MAG_HEADING );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Ground speed knots
//
ftoa( NmeaVTGData.GroundSpeedKnots, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_KNOTS );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Ground speed kilos
//
ftoa( NmeaVTGData.GroundSpeedKilos, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_KILOS );
// NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Check Sum
//
NMEAAddCheckSum( TransmitBuffer, &TXBufferIndex );
//
// CR/LF
//
NMEAAddCRLF( TransmitBuffer, &TXBufferIndex );
//
// Now send the sentence.
//
if( !ComPortWrite( ( unsigned char *)&TransmitBuffer[0], TXBufferIndex ) )
{
return NMEA_FAILED;
}
return NMEA_SUCCESS;
}
NMEA_STATUS NMEAGetGPRMCData( pNMEA_RMC_DATA pNmeaRMCData )
{
DMY Dmy;
unsigned long DateOfFix;
//
// Need to convert from degrees to degrees and minutes format.
//
pNmeaRMCData->TimeOfFixUTC = GetTimeOfFixUTC();
pNmeaRMCData->Status = NMEA_ACTIVE; // Cliff TODO
pNmeaRMCData->Lat = ConvertLatLonFromDegreestoDegreesMinutes( GetLatitudeAbs() );
pNmeaRMCData->NorthSouth = GetNorthSouth();
pNmeaRMCData->Long = ConvertLatLonFromDegreestoDegreesMinutes( GetLongitudeAbs() );
pNmeaRMCData->EastWest = GetEastWest();
pNmeaRMCData->GroundSpeedKnots = GetGroundSpeedKnots();
pNmeaRMCData->TrueHeading = GetTrueHeading();
GetDayMonthYear( &Dmy );
DateOfFix = ( ( unsigned long )Dmy.Day * 10000 ) + ( ( unsigned long )Dmy.Month * 100 ) + ( ( unsigned long )Dmy.Year - 2000 );
pNmeaRMCData->DateOfFix = DateOfFix;
return NMEA_SUCCESS;
}
/*
RMC - NMEA has its own version of essential gps pvt (position, velocity, time) data. It is called RMC, The Recommended Minimum, which will look similar to:
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
Where:
RMC Recommended Minimum sentence C
123519 Fix taken at 12:35:19 UTC
A Status A=active or V=Void. Not sure what is means??? TODO
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
022.4 Speed over the ground in knots
084.4 Track angle in degrees True
TODO Why do they have a different DMY format from the one that is in ZDA??
230394 Date - 23rd of March 1994
003.1,W Magnetic Variation
*6A The checksum data, always begins with *
Note that, as of the 2.3 release of NMEA, there is a new field in the RMC sentence at the end just prior to the checksum. For more information on this field see here.
*/
NMEA_STATUS NMEASendGPRMC( void )
{
NMEA_RMC_DATA NmeaRMCData;
char pFieldBuffer[ MAX_NMEA_FIELD ];
char TXBufferIndex = 0;
char TransmitBuffer[ MAX_NMEA_BUFFER ];
memset( TransmitBuffer,0, MAX_NMEA_BUFFER );
memset( &NmeaRMCData, 0, sizeof( NMEA_RMC_DATA ) );
//
// Get the necessary data from the FW.
//
NMEAGetGPRMCData( &NmeaRMCData );
TXBufferIndex = 0;
//
// Add the header
//
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_START );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_GPRMC );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Field 0 Time
//
// The time field must be 6 digits long. If the hour is less than 10 you
// must pad it with an extra zero.
//
sprintf( pFieldBuffer, "%06ld.00", ( long )NmeaRMCData.TimeOfFixUTC );
// ftod( NmeaRMCData.TimeOfFixUTC, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Active or Void
//
if( NmeaRMCData.Status == NMEA_ACTIVE )
{
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_ACTIVE_STR );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
}
else
{
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_VOID_STR );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
}
//
// Field 1 Latitude
//
ftod4( NmeaRMCData.Lat, pFieldBuffer ); // 4 decimal places
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Field 2 North/South
//
if( NmeaRMCData.NorthSouth == NMEA_SOUTH )
{
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_SOUTH );
}
else
{
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_NORTH );
}
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Field 3 Longitude
//
ftod4( NmeaRMCData.Long, pFieldBuffer ); // 4 decimal places
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Field 4 East/West
//
if( NmeaRMCData.EastWest == NMEA_WEST )
{
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_WEST );
}
else
{
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_EAST );
}
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Speed over the ground in knots.
//
ftodPrecision1( NmeaRMCData.GroundSpeedKnots, pFieldBuffer );
//ftod( NmeaRMCData.GroundSpeedKnots, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// True heading
//
ftodPrecision1( NmeaRMCData.TrueHeading, pFieldBuffer );
//ftod( NmeaRMCData.TrueHeading, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Date
//
itoa( NmeaRMCData.DateOfFix, pFieldBuffer, 10 );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// MagVar
//
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Check Sum
//
NMEAAddCheckSum( TransmitBuffer, &TXBufferIndex );
//
// CR/LF
//
NMEAAddCRLF( TransmitBuffer, &TXBufferIndex );
//
// Now send the sentence.
//
if( !ComPortWrite( ( unsigned char *)&TransmitBuffer[0], TXBufferIndex ) )
{
return NMEA_FAILED;
}
return NMEA_SUCCESS;
}
NMEA_STATUS NMEAGetGPZDAData( pNMEA_ZDA_DATA pNmeaZDAData )
{
DMY Dmy;
pNmeaZDAData->HrMinSecUTC = GetHrMinSecUTC();
GetDayMonthYear( &Dmy );
pNmeaZDAData->Day = Dmy.Day;
pNmeaZDAData->Month = Dmy.Month;
pNmeaZDAData->Year = Dmy.Year;
pNmeaZDAData->LocalTimeZoneHr = 8; // TODO
pNmeaZDAData->LocalTimeZoneMin = 19;
return NMEA_SUCCESS;
}
/*
ZDA - Data and Time
$GPZDA,hhmmss.ss,dd,mm,yyyy,xx,yy*CC
$GPZDA,201530.00,04,07,2002,00,00*6E
where:
hhmmss HrMinSec(UTC)
dd,mm,yyy Day,Month,Year
xx local zone hours -13..13
yy local zone minutes 0..59
*CC checksum
*/
NMEA_STATUS NMEASendGPZDA( void )
{
NMEA_ZDA_DATA NmeaZDAData;
char pFieldBuffer[ MAX_NMEA_FIELD ];
char TXBufferIndex = 0;
char TransmitBuffer[ MAX_NMEA_BUFFER ];
memset( TransmitBuffer,0, MAX_NMEA_BUFFER );
memset( &NmeaZDAData, 0, sizeof( NMEA_ZDA_DATA ) );
//
// Get the necessary data from the FW.
//
NMEAGetGPZDAData( &NmeaZDAData );
TXBufferIndex = 0;
//
// Add the header
//
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_START );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_GPZDA );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Time
//
// The time field must be 6 digits long. If the hour is less than 10 you
// must pad it with an extra zero.
//
sprintf( pFieldBuffer, "%06ld.00", ( long )NmeaZDAData.HrMinSecUTC );
// ftod( NmeaZDAData.HrMinSecUTC, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Day
//
sprintf( pFieldBuffer, "%02d", NmeaZDAData.Day );
//itoa( NmeaZDAData.Day, pFieldBuffer, 10 );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Month
//
sprintf( pFieldBuffer, "%02d", NmeaZDAData.Month );
//itoa( NmeaZDAData.Month, pFieldBuffer, 10 );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Year
//
itoa( NmeaZDAData.Year, pFieldBuffer, 10 );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Local time offset hour from UTC
//
sprintf( pFieldBuffer, "%02d", NmeaZDAData.LocalTimeZoneHr );
//itoa( NmeaZDAData.LocalTimeZoneHr, pFieldBuffer, 10 );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Local time offset minute from UTC
//
sprintf( pFieldBuffer, "%02d", NmeaZDAData.LocalTimeZoneMin );
//itoa( NmeaZDAData.LocalTimeZoneMin, pFieldBuffer, 10 );
NMEAAddField( TransmitBuffer, &TXBufferIndex, pFieldBuffer );
// NMEAAddField( TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA );
//
// Check Sum
//
NMEAAddCheckSum( TransmitBuffer, &TXBufferIndex );
//
// CR/LF
//
NMEAAddCRLF( TransmitBuffer, &TXBufferIndex );
//
// Now send the sentence.
//
if( !ComPortWrite( ( unsigned char *)&TransmitBuffer[0], TXBufferIndex ) )
{
return NMEA_FAILED;
}
return NMEA_SUCCESS;
}
void ftoaPrecision0( float value, char* strFloat )
{
sprintf( strFloat, "%d", value);
}
void ftoa( float value, char* strFloat )
{
sprintf( strFloat, "%.2f", value);
}
void ftod( double value, char* strDouble )
{
sprintf( strDouble, "%.2f", value );
}
void ftodPrecision1( double value, char* strDouble )
{
sprintf( strDouble, "%.1f", value );
}
void ftod4( double value, char* strDouble )
{
sprintf( strDouble, "%.4f", value ); // added two more decimal places
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -