⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nmea.c

📁 Construct NMEA packet in GPS module
💻 C
📖 第 1 页 / 共 3 页
字号:
/*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 + -