本博文讲述一个问题:PC上位机如何将串口接收到的GPS数据解析,并把位置信息显示在百度地图上?
1.串口接收GPS模块发送的数据,并将其显示在接收区
private string receiveData;
//接收数据
private void ReceiveData(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
receiveData = serial.ReadExisting();
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateTextDelegate(ShowData), receiveData);
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateTextDelegate(NMEADecodeGPS), receiveData);
}
//显示数据
private void ShowData(string text)
{
string receiveText = text;
try
{
//更新接收字节数
receiveBytesCount += (UInt32)receiveText.Length;
statusReceiveByteTextBlock.Text = receiveBytesCount.ToString();
//没有关闭数据显示
if (stopShowingButton.IsChecked == false)
{
//字符串显示
if (hexadecimalDisplayCheckBox.IsChecked == false)
{
receiveTextBox.AppendText( receiveText);
}
else //16进制显示
{
foreach (byte str in receiveText)
{
receiveTextBox.AppendText(string.Format("{0:X2} ", str));
}
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
2.调用nmealib库解析GPS原始数据,并显示相关信息
private void ReceiveData(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
receiveData = serial.ReadExisting();
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateTextDelegate(ShowData), receiveData);
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateTextDelegate(NMEADecodeGPS), receiveData);
}
//供串口接收到数据后调用,对接收到的品数据进行解码
private void NMEADecodeGPS(string gpsData)
{
nmea_parse(ref gpsParser, gpsData, gpsData.Length, ref gpsInfo);
UpdateInfo(ref gpsInfo);
}
#region nmea解码
//根据解码结果更新gps信息
private void UpdateInfo(ref nmeaINFO gpsInfo)
{
nmeaTIME beiJingTime = new nmeaTIME();
//转换成北京时间
GMTconvert(ref gpsInfo.utc,ref beiJingTime,8,1);
timeLabel.Content = Convert.ToString(beiJingTime.year) + "年" + Convert.ToString(beiJingTime.mon) + "月" + Convert.ToString(beiJingTime.day) + "日" + Convert.ToString(beiJingTime.hour) + ":" + Convert.ToString(beiJingTime.min) + ":" + Convert.ToString(beiJingTime.sec);
//经度
longitudeLabel.Content = Convert.ToString(DegreeConvert(gpsInfo.lon))+" E";
//纬度
latitudeLabel.Content = Convert.ToString(DegreeConvert(gpsInfo.lat))+" N";
elevatiionLabel.Content = Convert.ToString(gpsInfo.elv)+" 米";
speedLabel.Content = Convert.ToString(gpsInfo.speed)+" km/h";
directionLabel.Content = Convert.ToString(gpsInfo.declination);
switch (gpsInfo.sig)
{
case 0:
signalLevalLabel.Content = "未定位";
break;
case 1:
signalLevalLabel.Content = "标准GPS定位";
break;
case 2:
signalLevalLabel.Content = "差分GPS定位";
break;
default:
break;
}
switch (gpsInfo.fix)
{
case 1:
operationModeLabel.Content = "未定位";
break;
case 2:
operationModeLabel.Content = "2D定位";
break;
case 3:
operationModeLabel.Content = "3D定位";
break;
default:
break;
}
sateliteInView.Content = Convert.ToString(gpsInfo.satinfo.inview)+" 颗";
sateliteInUse.Content = Convert.ToString(gpsInfo.satinfo.inuse) + " 颗";
positionPrecisionLabel.Content = Convert.ToString(gpsInfo.PDOP);
horizontalPrecisionLabel.Content = Convert.ToString(gpsInfo.HDOP);
verticalPrecisionLabel.Content = Convert.ToString(gpsInfo.VDOP);
if (baiDuMap.IsLoaded)
{
//非零时才作标注
if(gpsInfo.lon!=0 &&gpsInfo.lat!=0)
{
//调用javascritpt函数标注地图
WebBrowser mapWB = (WebBrowser)baiDuMap.Content;
mapWB.InvokeScript("theLocation", new object[] { DegreeConvert(gpsInfo.lon) , DegreeConvert(gpsInfo.lat) });
}
}
}
//对gps日志文件进行解码
public void NMEADecodeGPSLog(string path)
{
string readbuf = "";
try
{
nmea_zero_INFO(ref gpsInfo);
nmea_parser_init(ref gpsParser);
gpsInfoTabControl.SelectedIndex = 1;
foreach (string line in File.ReadLines(path))
{
readbuf = line + "\r\n";
nmea_parse(ref gpsParser, readbuf, readbuf.Length, ref gpsInfo);
UpdateInfo(ref gpsInfo);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
//供串口接收到数据后调用,对接收到的品数据进行解码
private void NMEADecodeGPS(string gpsData)
{
nmea_parse(ref gpsParser, gpsData, gpsData.Length, ref gpsInfo);
UpdateInfo(ref gpsInfo);
}
#endregion
private void GPSFrame_Navigated(object sender, NavigationEventArgs e)
{
//serialSettingBorder.IsEnabled = true;
//serialPortControlBorder.IsEnabled = true;
}
}
gpsInfo结构体中存放着nmea解析后的所有GPS信息
nmeaINFO gpsInfo = new nmeaINFO();
public struct nmeaINFO
{
public int smask; /**< Mask specifying types of packages from which data have been obtained */
public nmeaTIME utc; /**< UTC of position */
public int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
public int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
public double PDOP; /**< Position Dilution Of Precision */
public double HDOP; /**< Horizontal Dilution Of Precision */
public double VDOP; /**< Vertical Dilution Of Precision */
public double lat; /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
public double lon; /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
public double elv; /**< Antenna altitude above/below mean sea level (geoid) in meters */
public double speed; /**< Speed over the ground in kilometers/hour */
public double direction; /**< Track angle in degrees True */
public double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
public nmeaSATINFO satinfo; /**< Satellites information */
}
3.调用百度地图,将经纬度信息显示在地图上
if (baiDuMap.IsLoaded)
{
//非零时才作标注
if(gpsInfo.lon!=0 &&gpsInfo.lat!=0)
{
//调用javascritpt函数标注地图
WebBrowser mapWB = (WebBrowser)baiDuMap.Content;
mapWB.InvokeScript("theLocation", new object[] { DegreeConvert(gpsInfo.lon) , DegreeConvert(gpsInfo.lat) });
}
}