在线紧急求助:garmin手持机的已存的路点数据如何上传到PC? ( 积分: 100 )

  • 主题发起人 liuql188
  • 开始时间
L

liuql188

Unregistered / Unconfirmed
GUEST, unregistred user!
我使用的是garmin公司的奇遇手持机,用于采集电杆的点位信息,
请问如何把保存在手持机中的点位信息上传到电脑中??
我用的是delphi+mapX,已经下载了garmin公司的协议(E文的),
用SPComm控件实现RS232的数据传输。
好像是需要向手持机发送A100协议,然后接收D108协议格式,
但是我不知道具体如何实现,哪位大侠能提供一段示范代码?
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
我记得发过一次如何解Garmin协议的文章和代码。
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
一下没找到,这样我给你说几点吧。
1,你必须首先熟悉串口通讯的相关知识,如波特率,奇偶校验等,如果你用SPCOMM会简单
一些;
2,Garmin协议中那么多的协议,你不用都去管,因为很多都是链路层的,比如机器与机器之间的航点交换等;你只需要关心以下的几条协议就可以了:
A,D108,航点WayPoint协议;(老的12系列机器也有用D100的,不过估计你碰不到)
B,D201,航线route协议,其中包含的航点数据,也是用D108来解析;航线连接点数据是D210协议;
C,D301,航迹Track协议,其中航迹头的解析用D310.

3,Garmin协议是二进制通讯协议,以#16开始,#16#3结尾,第1个字节是命令字节(从0开始算,第0个字节就是#16),比如 Pid_Wpt_Data = #35 指的本条报文是航点数据;命令有很多,包括ACK等,我列几个,更多的命令定义可以看PDF。
Pid_Command_Data = 10;
Pid_Xfer_Cmplt = 12;
Pid_Date_Time_Data = 14;
Pid_Position_Data = 17;
Pid_Prx_Wpt_Data = 19;
Pid_Records = 27;
Pid_Rte_Hdr = 29;
Pid_Rte_Wpt_Data = 30;
Pid_Almanac_Data = 31;
Pid_Trk_Data = 34;
Pid_Wpt_Data = 35;
Pid_Pvt_Data = 51;
Pid_Rte_Link_Data = 98;
Pid_Trk_Hdr = 99;
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
再往下,第2个字节则是报文内容长度标识字节,指示了从第3个字节到CheckSum字节前的报文长度。CheckSum之后就是结束符#16#3 .
 
L

liuql188

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢吕雪松老师的指导,我现在是不知道如何命令手持机开始向电脑发送航点报文??
是否这样??
1、向手持机发送:#16??#16#3 (??代表指令)
2、等待:#16#35.....#16#3格式的报文出现并接收处理。
还是不用发送命令,手持机一直在不停地发送数据,直接接收即可??
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
Garmin协议是每一条都要应答的,否则下一条就发不了。举个例子:
PC ---请求发送WayPoint--> GPS
PC <-------ACK----------- GPS
PC <----WayPoint-D108---- GPS
PC --------ACK----------> GPS
PC <----WayPoint-D108---- GPS
PC --------ACK----------> GPS
...
PC <----WayPoint-结束---- GPS
 
L

liuql188

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢吕老师,感觉好复杂呀,毕竟第一次接触gps。

吕老师,能否麻烦你找一段示范代码发给我,Email:qq3076169@126.com

不胜感激,若能收到示范程序,将另开贴加200分。
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
不用单独发给你,我就帖一点在这里吧,其他朋友感兴趣也可以分享,以下是航点解析的函数。

//解析GPS发送来的航点数据包
procedure TCommForm.Translate_D108_Wpt_type(Package : string);
var
XX,YY :do
uble;
WPt : TGPSWayPoint;
//航点类,没什么特别的,你可以设计你自己的。
szSubPack : string;
begin

WPt := TGPSWayPoint.Create;//建一个航点实例

szSubPack:=Copy(Package,52,length(Package)-48);//取航点名称,可以是中文,注意有可能有很多空格,早期etrex大概只有5个汉字,而后期的和航海GPS可能有很长的中文名
Wpt.Name := Copy(szSubPack, 1, Pos(#0, szSubPack) - 1);

Wpt.Name := Trim(Wpt.Name);
Delete(szSubPack, 1, Pos(#0, szSubPack));
wpt.comment := Copy(szSubPack, 1, Pos(#0, szSubPack) - 1);//取其中的备注部分,一般是空的,Vista可能会把建立航点的时间写在这里。

Wpt.wpt_class := Ord(Package[4]);

wpt.color := Ord(Package[5]);
{ Black, Dark_Red, Dark_Green, Dark_Yellow,
Dark_Blue, Dark_Magenta, Dark_Cyan, Light_Gray,
Dark_Gray, Red, Green, Yellow,
Blue, Magenta, Cyan, White,
Default_Color = 0xFF
}
wpt.dspl := Ord(Package[6]);
wpt.Alt := GetSingleData(Package,36,4);
if Wpt.Alt > 10E10 then
Wpt.Alt := 0;
wpt.dpth := GetSingleData(Package,40,4);
if Wpt.Dpth > 10E10 then
Wpt.Dpth := 0;
wpt.Dist := GetSingleData(Package,44,4);
if Wpt.Dist > 10E10 then
Wpt.Dist := 0;
{
dspl_name = 0, /* Display symbol with waypoint name */
dspl_none = 1, /* Display symbol by itself */
dspl_cmnt = 2 /* Display symbol with comment */
}
wpt.attr := Ord(Package[7]);
{ The “attr” member should be set to a value of 0x60.}
wpt.smbl := GetIntData(Package,8,2);


YY := GetCoordinate(Copy(Package,28,4));
XX := GetCoordinate(Copy(Package,32,4));

WPt.AddPt(XX,YY);
end;
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
涉及到的几个小函数:
//从报文中解析坐标
function GetCoordinate(Semicircle : string) :do
uble; //4 char
begin

result := (Ord(SemiCircle[1]) + Ord(SemiCircle[2]) * Power(2,8) + Ord(SemiCircle[3]) * Power(2,16) + Ord(SemiCircle[4]) * Power(2,24)) * 180/Power(2,31);
end;


//根据字节计算出整数来
function GetIntData(strData: string;
nbegin
Pos, nLength: integer): integer;
var
I : integer;
begin

result := 0;
for I := 1 to nLengthdo
begin

result := result + Round(Ord(StrData[nbegin
Pos + (I - 1)]) * Power(2,8 * (I - 1)));
end;

end;
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
好了就这些,应该可以帮助你实现航点下载了。我的源代码是一个软件产品,封装得很厉害,协议解析这部分很复杂,因为不光要解析Garmin协议,还有NMEA和GSM SM等,所以设计了一很复杂的协议分析类,没法都给你,给你估计你也会看晕掉的。
 

吕雪松

Unregistered / Unconfirmed
GUEST, unregistred user!
还忘记两个比较重要的函数:发送ACK应答和计算CheckSum
procedure SendACK(RecByte : Byte);
var
sPack : string;
begin

sPack := #16;
sPack := sPack + Chr(Pid_Ack_Byte);
sPack := sPack + #2;
sPack := sPack + Chr(RecByte);
sPack := sPack + #0#0#16#3;
CalcCheckSum(sPack);
if SysInfo.bGPSConnected then
SendToDevice(sPack);
end;


function CalcCheckSum(var sPack : string) : integer;
var
nCheckByte : Byte;
I : integer;
begin

try
nCheckByte := 0;
for I := 0 to Ord(sPack[3])do
begin

nCheckByte := nCheckByte + Ord(sPack[I + 2]);
end;

sPack[4 + Ord(sPack[3])] := Chr(256 - nCheckByte);
result := Ord(sPack[4 + Ord(sPack[2])]);
//#16->#16#16
FixPackage(sPack);
except
end;

end;


注意,由于Garmin协议将#16用做控制符,因此,报文中数据部分的#16字符都用#16#16来替换,所以在接收时,要将报文中的#16#16替换成#16,发送ACK是,要将数据部分的#16用#16#16来代替,fixPackage就是拿来做这件事的,你自己写吧,我就不帖了。
 
L

liuql188

Unregistered / Unconfirmed
GUEST, unregistred user!
非常感谢吕雪松老师详尽的解答,
有你的帮助至少让我节省了半个月的冥思苦想。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
顶部