在2008年上半年就曾经深刻研究过GPS,当时还觉得已经相对全面的了解GPS呢,如今从新拾起去研究GPS技术,发现仍是差了一大截。最初觉得GPS是单向通讯,GPS模块按照固定的时间间隔发送文本格式的GPS数据。如今才知道GPS不只能够双向通讯,还能够以二进制格式收发数据,而且能够配置须要发送数据的种类和发送间隔,固然必要的时候,还能够用专门的工具,更新GPS模块的固件。git
最初了解GPS,是基于WINCE平台,为写一本书而作,详情请参见《实战WindowsEmbedded CE 6.0—GPS篇》和《个人第一个WINCE驱动》。后来为了便于调试,又把程序移植到Windows Mobile手机上(采用.NET精简框架集的Winform完成,本篇.NET MF界面代码就是基于原先的这套代码,稍做改进而来,而底层接收代码,添加了校验和更全的GPS命令解析),相关博文请参见《GPS NMEA0183协议解析》。编程
如今从新研究GPS,是为物联网网关系统封装一个GPS库,最初的时候,购买了几个低价二手的GPS模块,可是却没法定位,在阳台附近没法定位也就算了,可是我直接到空旷的大操场也没法定位,而且没有一个星的信号。因此后来只好又购买一个价钱较高,带有源天线的GPS模块。windows
这个带外接天线的模块果真不错,信号强度蛮强,可是我在购买的时候犯了一个错误,选型的时候,选择了“4800bps GPRMC数据包输出,不带PPS”,因此就只能输出$GPRMC基本信息了,可是这样星图就没法显示了。框架
因为技术支持不在线,因此只好先本身想办法解决这个问题了。我想应该有两种思路能够解决这个问题,一是更新固件。可是这种方法显然须要技术支持来提供相应固件,若是本身找相关工具和固件进行烧写,不免会出问题(后来问了技术支持才知道,还得飞一个线,进入烧写模式才行);二是配置信息输出。这种方法最方便,问题是,掉电配置就丢失了,可是这个GPS板子带纽扣电池,因此问题不大。ide
有了第二种思路,而后网上就进行搜索,果真功夫不负有心人,搜到了以下信息:函数
NMEA信息输出控制工具
$PSRF103,00,01,00,01*25<CR><LF>测试
格式说明(Set Serial Port Data Format):spa
Name.net |
Example |
Unit |
Description |
Message ID |
$PSRF103 |
|
PSRF103 protocol header |
Msg |
00 |
|
0:GGA 1:GLL 2:GSA 3:GSV 4:RMC 5:VTG 6:MSS (If internal beacon is supported) 7:Not defined 8:ZDA (if 1PPS output is supprttd) 9:Not defined |
Mod |
01 |
|
0 = Set Rate 1 = Query one time 2 = ABP On 3 = ABP Off |
Rate |
00 |
|
Output Rate: 0 = Off 1–255 = seconds between messages |
CksumEnable |
01 |
|
0=Disable Checksum 1=Enable Checksum |
Checksum |
*25 |
|
|
<CR><LF> |
|
|
End of message termination |
示例 |
关闭GGA: $PSRF103,00,00,01,01*25 设置GGA为5秒输出一次: $PSRF103,00,00,05,01*21
关闭GSA: $PSRF103,02,00,00,01*26 设置GSA为5秒输出一次: $PSRF103,02,00,05,01*23 |
可是因为NMEA有校验,因此还须要一个专门的工具来设置才行,因此又找到了SiRFLive软件,这个软件很不错,能够方便的调试GPS模块。也许是供电的问题,我此次在阳台测试我原先的GPS模块,竟然能够定位成功了。下图即是该GPS模块使用SiRFLive软件进行测试的效果图。
若是须要配置GPS,直接进入命令发送窗口便可,记得选择NMEA协议。
修改了相关配置,新购买的GPS果真能够输出星图信息了,在物联网智能网关上的运行效果图以下:
GPS库相关内容我这里就不细说了,文档里面有详细的说明。我这里说一下,在.NET Micro Framework平台,如何进行Winform界面开发(WinForm for .NET MF 功能一览)。
本实例程序,GPS相关函数一旦执行,会自动把GPS模块的相关参数赋值到GPS类的相关属性中去。界面绘图咱们采用重载Form类的OnPaint方法,为了不闪烁,咱们还采用了在Windows编程中常见的技巧,就是重载OnPaintBackground方法,不去绘制背景。
protected override void OnPaint(PaintEventArgse)
{
try
{
e.Graphics.Clear(Color.Gray); //绘制背景
//--------------------------
//绘制信噪比图
DrawSNR(e.Graphics, new Rectangle(2,240 - 80, 320 - 4, 80));
//绘制星图
DrawSatellite(e.Graphics, new Rectangle(10,60, 100, 100));
//状态
e.Graphics.DrawString("状态:" + (GPS.Online ? "已链接 " : "未链接 ") + (GPS.Manage.AnchorState == "A" ? "已定位" : "未定位"), font, sb, 5, 8);
//坐标
e.Graphics.DrawString("坐标:" + GPS.Manage.ToString("D"),font, sb, 5, 25);
//pb_Graphics.DrawString("坐标:" + GPS.Manage.Latitude.ToString()+ " " + NMEA.GPS.Longitude.ToString(), font, newSolidBrush(Color.White), 5, 25);
//时间
e.Graphics.DrawString("时间:" + GPS.Manage.UTCDateTime.ToString(), font, sb,150, 25);
//-------------------------------
//卫星数
e.Graphics.DrawString("卫星:" + GPS.Manage.SatelliteNum.ToString() + " 颗", font, sb, 130, 60);
//定位状态 0=未定位,1=GPS单点定位固定解,2=差分定位,3=无效PPS,4=RTK固定解,5=RTK浮点解,6=估计值,7=手工输入模式,8=模拟模式
e.Graphics.DrawString("状态:" + strState[GPS.Manage.AnchorSStateEx], font, sb,130, 75);
//获取定位模式(A=自动,M=手动)。
e.Graphics.DrawString("模式:" + (GPS.Manage.AnchorMode == "A" ? "自动" : "手动"), font, sb, 130, 90);
//定位类型(1=未定位,2=2D定位,3=3D定位)
e.Graphics.DrawString("类型:" + strType[GPS.Manage.AnchorType], font, sb, 130,105);
//海拔
e.Graphics.DrawString("海拔:" + GPS.Manage.Altitude.ToString("F2") + "("+ GPS.Manage.Height.ToString("F2")+ ")", font, sb, 130, 120);
//速度
e.Graphics.DrawString("速度:" + GPS.Manage.KSpeed.ToString("F2"), font, sb, 130, 135);
//方向
e.Graphics.DrawString("方向:" + GPS.Manage.Track.ToString("F2"), font, sb, 130, 150);
//信息
Microsoft.SPOT.Debug.Print(GPS.ErrorMessage);
}
catch {}
}
具体绘制绘制信噪比图的代码以下:
private void DrawSNR(Graphicse, Rectangle rect)
{
Fontfont = new Font("Arial", 9, FontStyle.Regular);
intFontHeight = 20;
int SNRHeight= rect.Height - FontHeight;
intSNRWidth = (rect.Width - FontHeight / 2) / 12;
//绘制信噪比图
e.DrawLine(newPen(Color.Gray),rect.Left, rect.Top, rect.Right, rect.Top);
e.DrawLine(newPen(Color.Gray),rect.Left, rect.Top + SNRHeight / 2, rect.Right, rect.Top + SNRHeight / 2);
e.DrawLine(newPen(Color.Gray),rect.Left, rect.Top + SNRHeight, rect.Right, rect.Top + SNRHeight);
for (int i = 0; i < 12; i++)
{
stringstrPRN = GPS.Manage.Satellite[i].PRN.ToString();
if(strPRN.Length == 1) strPRN = "0"+ strPRN;
intHeight = (int)(GPS.Manage.Satellite[i].SNR *SNRHeight / 100);
intfont_h, font_w;
font.Value.ComputeExtent(strPRN, out font_w, outfont_h);
//星号
e.DrawString(strPRN, font, new SolidBrush(Color.White), (int)(rect.Left+ FontHeight / 4 + SNRWidth * i), (int)(rect.Top+ SNRHeight + 4));
//信噪比
e.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(rect.Left + FontHeight / 4 + SNRWidth *i, rect.Top + SNRHeight - Height, font_w, Height));
}
}
绘制星图的代码以下:
private voidDrawSatellite(Graphics e, Rectangle rect)
{
Fontfont = new Font("Arial", 9, FontStyle.Regular);
int X = rect.Left + rect.Width / 2;
int Y =rect.Top + rect.Height / 2;
intSize = (rect.Width > rect.Height ? rect.Height : rect.Width);
int R =(Size - 12 * 2) / 6;
int r =8;
e.DrawLine(newPen(Color.Red),X - R * 3 - 12, Y, X + R * 3 + 12, Y);
e.DrawLine(newPen(Color.Red),X, Y - R * 3 - 12, X, Y + R * 3 + 12);
e.DrawEllipse(newPen(Color.Blue),new Rectangle(X- R, Y - R, R * 2, R * 2));
e.DrawEllipse(newPen(Color.Blue),new Rectangle(X- R * 2, Y - R * 2, R * 4, R * 4));
e.DrawEllipse(newPen(Color.Blue),new Rectangle(X- R * 3, Y - R * 3, R * 6, R * 6));
e.DrawString("N",font, new SolidBrush(Color.White), X + 2, Y - R * 3 - 10);
e.DrawString("S",font, new SolidBrush(Color.White), X + 2, Y + R * 3 + 2);
e.DrawString("W",font, new SolidBrush(Color.White), X - R * 3 - 10, Y + 2);
e.DrawString("E",font, new SolidBrush(Color.White), X + R * 3 + 2, Y + 2);
//绘制卫星位置
int X0= 0, Y0 = 0, L = 0;
doubleA1 = 0, A2 = 0;
StringFormatsFormat = new StringFormat();
sFormat.Alignment = StringAlignment.Center;
sFormat.LineAlignment = StringAlignment.Center;
for (int i = 0; i < 12; i++)
{
if(GPS.Manage.Satellite[i].PRN > 0)
{
A1 =GPS.Manage.Satellite[i].Elevation * Math.PI/ 180;
A2 =GPS.Manage.Satellite[i].Azimuth * Math.PI /180;
L = (int)(Math.Cos(A1) * 3 * R);
X0 = X + (int)(Math.Cos(Math.PI * 5 / 2 - A2) * L);
Y0 = Y - (int)(Math.Sin(Math.PI * 5 / 2 - A2) * L);
e.FillEllipse(new SolidBrush(Color.Blue), new Rectangle(X0 - r, Y0 - r, 2 * r, 2 * r));
e.DrawString(GPS.Manage.Satellite[i].PRN.ToString(),font, new SolidBrush(Color.White), new Rectangle(X0 - r * 2, Y0 - r * 2, 4 * r, 4 * r),sFormat);
}
}
}
从以上代码能够看出,在.NET Micro Framework系统中开发WinForm程序,和上位机没有什么区别,上面的代码也基本上也能够在windows桌面.Net程序中直接可使用。
下载地址:http://www.sky-walker.com.cn/MFRelease/library/V42/YFSoft.Hardware.GPS.rar