📄 nmea.c
字号:
/*extern char gSimulate;*/voidSendNMEA (void){ if (GPGGA != 0) NMEASendGPGGA (); /* NMEA, use sentance options */ if (GPGSA != 0) NMEASendGPGSA (); if (GPGSV != 0) NMEASendGPGSV (); if (GPRMC != 0) NMEASendGPRMC (); if (GPZDA != 0) NMEASendGPZDA ();}/** * NMEA Notes * * Longitude and latitude can be expressed in several different * representations: * * dms (deg,min,sec) - Degrees, minutes and seconds format * (e.g. 5045'23.99") * * degrees - Decimal degrees (e.g. 50.7567) * * radians - Radians (e.g. 0.88587090) * * degrees, minutes - Degrees and minutes format (e.g. 5045.3998') * * Select the appropriate representation found in the string files * * Converting Between Decimal Degrees, Degrees, Minutes and Seconds, * and Radians (dd + mm/60 +ss/3600) to Decimal degrees (dd.ff) * * dd = whole degrees, mm = minutes, ss = seconds * * dd.ff = dd + mm/60 + ss/3600 * * Example: 30 degrees 15 minutes 22 seconds = 30 + 15/60 + * 22/3600 = 30.2561 * * Decimal degrees (dd.ff) to (dd + mm/60 +ss/3600) * * For the reverse conversion, we want to convert dd.ff to dd mm * ss. Here ff = the fractional part of a decimal degree. * * mm = 60*ff * * ss = 60*(fractional part of mm) * * Use only the whole number part of mm in the final result. * * 30.2561 degrees = 30 degrees * * .2561*60 = 15.366 minutes * * .366 minutes = 22 seconds, so the final result is 30 degrees 15 * minutes 22 seconds * * Decimal degrees (dd.ff) to Radians * * Radians = (dd.ff)*pi/180 * * Radians to Decimal degrees (dd.ff) * * (dd.ff) = Radians*180/pi * * Degrees, Minutes and Seconds to Distance * * A degree of longitude at the equator is 111.2 kilometers. A minute * is 1853 meters. A second is 30.9 meters. For other latitudes * multiply by cos(lat). Distances for degrees, minutes and seconds in * latitude are very similar and differ very slightly with latitude. * (Before satellites, observing those differences was a principal * method for determining the exact shape of the earth.) * * * D = Degrees * M = Minutes * S = Seconds * .m = Decimal Minutes * .s = Decimal Seconds * * DM.m = Degrees, Minutes, Decimal Minutes (eg. 45 22.6333) * D.d = Degrees, Decimal Degrees (eg. 45.3772) * DMS = Degrees, Minutes, Seconds (eg. 45 22'38") * * Process for Converting Latitude/Longitude Coordinates: * * 1) DMS --> DM.m (45o22'38" --> 45o22.6333) * * - Divide S by 60 to get .m (38/60=.6333) * - Add .m to M to get M.m (22+.6333=22.6333) * * 2) DM.m --> D.d (45o 22.6333 --> 45.3772) * * - Divide M.m by 60 to get .d (22.6333/60=.3772) * - Add .d to D to get D.d (45+.3772=45.3772) * * 3) D.d --> DM.m ( 45.3772 --> 45 22.6333) * * - Multiply .d by 60 to get M.m (.3772 * 60 = 22.6333) * * 4) DM.m --> DMS (45o22.6333 --> 45 22'38") * * - Multiply .m by 60 to get S(.6333*60=38) * * * Converting Degrees, Minutes, Seconds to Decimal Format * * latitude and longitude in a decimal format: 42.1361 * * latitude and longitude in degree, minute, second format: 42deg, * 08min, 10sec * * To convert coordinates from degrees, minutes, seconds format to * decimal format, use this easy formula: * * degrees + (minutes/60) + * (seconds/3600) * * The example coordinate above would be * calculated as: * 42 + (8/60) + (10/3600) = 42.1361 * or * 42 + (.1333) + (.0028) = 42.1361 * * **/voidNMEAAddCRLF (char *TransmitBuffer, int *TXBufferIndex){ char *TempPtr = TransmitBuffer + *TXBufferIndex; *TempPtr++ = 0x0D; *TempPtr++ = 0x0A; /** * Update the index. **/ *TXBufferIndex += 2; *TempPtr++ = '\0';}voidNMEAAddField (char *TransmitBuffer, int *TXBufferIndex, char *StringToAdd){ int NumberOfChars = 0; NumberOfChars = strlen (StringToAdd); /** * Copy the data. **/ memcpy (&TransmitBuffer[*TXBufferIndex], StringToAdd, NumberOfChars); /** * Update the index. **/ *TXBufferIndex += NumberOfChars;}doubleConvertLatLonFromDegreestoDegreesMinutes (double PositionDegrees){ double Degrees = (int) PositionDegrees; double Minutes = PositionDegrees - Degrees; double DegreesMinutes = Minutes * 60 + (Degrees * 10 * 10); return DegreesMinutes;}/** * The checksum is the 8-bit exclusive OR (no start or stop bits) of * all characters in the sentence, including the "," delimiters, * between -- but not including -- the "$" and "*" delimiters. * * The hexadecimal value of the most significant and least significant * 4 bits of the result are converted to two ASCII characters (0-9, * A-F) for transmission. The most significant character is * transmitted first. **/unsigned charCalculateNmeaCheckSum (char *NmeaSentence){ int Index; unsigned char NmeaCheckSum = 0; for (Index = 1; NmeaSentence[Index] != '*'; Index++) { NmeaCheckSum ^= NmeaSentence[Index]; } return NmeaCheckSum;}voidNMEAAddCheckSum (char *TransmitBuffer, int *TXBufferIndex){ unsigned char CheckSum; unsigned char TXCheckSum; char TempBuf[10]; NMEAAddField (TransmitBuffer, TXBufferIndex, NMEA_SENTENCE_ASTERISK); CheckSum = CalculateNmeaCheckSum (TransmitBuffer); TXCheckSum = CheckSum & 0xf0; TempBuf[0] = (TXCheckSum >> 4) + '0'; TempBuf[1] = '\0'; if (TempBuf[0] > '9') { TempBuf[0] += 'A' - ('9' + 1); TempBuf[1] = '\0'; } NMEAAddField (TransmitBuffer, TXBufferIndex, TempBuf); TXCheckSum = CheckSum & 0x0f; TempBuf[0] = (TXCheckSum & 0xf) + '0'; TempBuf[1] = '\0'; if (TempBuf[0] > '9') { TempBuf[0] += 'A' - ('9' + 1); TempBuf[1] = '\0'; } NMEAAddField (TransmitBuffer, TXBufferIndex, TempBuf);}NMEA_STATUSNMEAGetGPGGAData (pNMEA_GGA_DATA pNmeaGGAData){ /** * Need to convert from degrees to degrees and minutes format. **/ pNmeaGGAData->TimeOfFixUTC = GetTimeOfFixUTC (); pNmeaGGAData->Lat = ConvertLatLonFromDegreestoDegreesMinutes (GetLatitudeAbs ()); pNmeaGGAData->NorthSouth = GetNorthSouth (); pNmeaGGAData->Long = ConvertLatLonFromDegreestoDegreesMinutes (GetLongitudeAbs ()); pNmeaGGAData->EastWest = GetEastWest (); pNmeaGGAData->FixQuality = GetFixQuality (); pNmeaGGAData->NumberOfTrackingSV = GetNumberOfTrackingSVs (); pNmeaGGAData->HDOP = GetHDOP (); pNmeaGGAData->Altitude = GetAltitude (); pNmeaGGAData->HeightOfGeoid = GetHeightOfGeoid (); return NMEA_SUCCESS;}/** * GGA - essential fix data which provide 3D location and accuracy data. * * $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 * * Where: * GGA Global Positioning System Fix Data * 123519 Fix taken at 12:35:19 UTC * 4807.038,N Latitude 48 deg 07.038' N * 01131.000,E Longitude 11 deg 31.000' E * 1 Fix quality: 0 = invalid * 1 = GPS fix (SPS) * 2 = DGPS fix * 3 = PPS fix * 4 = Real Time Kinematic * 5 = Float RTK * 6 = estimated (dead reckoning) (2.3 feature) * 7 = Manual input mode * 8 = Simulation mode * 08 Number of satellites being tracked * 0.9 Horizontal dilution of position * 545.4,M Altitude, Meters, above mean sea level * 46.9,M Height of geoid (mean sea level) above WGS84 ellipsoid * (empty field) time in seconds since last DGPS update * (empty field) DGPS station ID number * *47 the checksum data, always begins with * * * If the height of geoid is missing then the altitude should be suspect. * * Some non-standard implementations report altitude with respect to * the ellipsoid rather than geoid altitude. Some units do not report * negative altitudes at all. This is the only sentence that reports * altitude. * **/NMEA_STATUSNMEASendGPGGA (void){ NMEA_GGA_DATA NmeaGGAData; char pFieldBuffer[MAX_NMEA_FIELD]; int TXBufferIndex = 0; char TransmitBuffer[MAX_NMEA_BUFFER]; memset (TransmitBuffer, 0, MAX_NMEA_BUFFER); /** * Get the necessary data from the FW. **/ NMEAGetGPGGAData (&NmeaGGAData); /** * Add the header **/ NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_START); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_GPGGA); 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) NmeaGGAData.TimeOfFixUTC); /* ftod( NmeaGGAData.TimeOfFixUTC, pFieldBuffer ); */ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 1 Latitude **/ ftod4 (NmeaGGAData.Lat, pFieldBuffer); /* 4 decimal places */ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 2 North/South **/ if (NmeaGGAData.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 (NmeaGGAData.Long, pFieldBuffer); /* 4 decimal places */ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 4 East/West **/ if (NmeaGGAData.EastWest == NMEA_WEST) { NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_WEST); } else { NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_EAST); } NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 5 Fix Quality **/ sprintf (pFieldBuffer, "%d", NmeaGGAData.FixQuality); /* ftod( NmeaGGAData.FixQuality, pFieldBuffer ); */ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 6 Number of SV's used. **/ sprintf (pFieldBuffer, "%02d", NmeaGGAData.NumberOfTrackingSV); /*itoa( NmeaGGAData.NumberOfTrackingSV, pFieldBuffer, 10 );*/ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 7 HDOP **/ ftodPrecision1 (NmeaGGAData.HDOP, pFieldBuffer); /* ftod( NmeaGGAData.HDOP, pFieldBuffer ); */ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 8 Altitude **/ ftodPrecision1 (NmeaGGAData.Altitude, pFieldBuffer); /* ftod( NmeaGGAData.Altitude, pFieldBuffer ); */ NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 9 Altitude Units **/ NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_UNITS_METERS); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 10 Geoid Seperation ( Height of geoid above WGS84 ellipsoid ) **/ ftodPrecision1 (0.0, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, pFieldBuffer); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 11 Geoid Seperation units **/ NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_UNITS_METERS); NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 12 DGPS Age **/ NMEAAddField (TransmitBuffer, &TXBufferIndex, NMEA_SENTENCE_COMMA); /** * Field 12 DGPS StationID **/ /** * Check Sum **/ NMEAAddCheckSum (TransmitBuffer, &TXBufferIndex); /** * CR/LF **/ NMEAAddCRLF (TransmitBuffer, &TXBufferIndex); /** * Now send the sentence. **/ if (!ComPortWrite ((unsigned char *) &TransmitBuffer[0], TXBufferIndex)) { return NMEA_FAILED; } else { return NMEA_SUCCESS; }}NMEA_STATUSNMEAGetGPGSAData (pNMEA_GSA_DATA pNmeaGSVData){ int i; TRACKING_PRNs TrackingPRNs[12]; memset (TrackingPRNs, 0, sizeof (TrackingPRNs)); pNmeaGSVData->Mode = NMEA_MODE_A; /* Cliff */ if (GetNavStatus ()) { pNmeaGSVData->FixMode = NMEA_FIX_MODE_3D_FIX; } else { pNmeaGSVData->FixMode = NMEA_FIX_MODE_NO_FIX; }/* if (gSimulate) { pNmeaGSVData->FixMode = NMEA_FIX_MODE_3D_FIX; } */ GetTrackingPRNs (&TrackingPRNs[0]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -