Qt实现GPS协议-NMEA0183

要实现GPS的解析和显示经纬度等信息,在硬件上最方便的就是使用一个GPS模块,比如ublox模块,这个厂家的产品基本上算是市场占有率第一的。然后ublox模块可以通过串口或者usb来和SYSZUX PAD(或者其它的什么显示电路)来通信。

      Ublox模块启动后会先发送一些ublox公司相关信息的文本,然后会按照NMEA0183标准协议来传送GPS定位数据,gemfield的Qt端做的就是解析这些数据。一般情况下,ublox模块一秒钟发送一组定位的相关信息,这些信息是文本格式,大致内容如下:
$GPVTG,18.89,T,,M,1.422,N,2.634,K,A*03
$GPGGA,070054.00,3958.45919,N,11619.78649,E,1,04,7.29,0.0,M,-8.7,M,,*4D
$GPGSA,A,2,24,29,05,10,,,,,,,,,7.36,7.29,1.00*05
$GPGSV,3,1,09,01,06,260,,02,63,098,,04,22,111,,05,74,323,39*7C
$GPGSV,3,2,09,07,12,062,25,10,68,028,37,24,35,305,35,25,09,044,29*72
$GPGSV,3,3,09,29,42,299,35*49
$GPGLL,3958.45919,N,11619.78649,E,070054.00,A,A*62
$GPRMC,070055.00,A,3958.45914,N,11619.78689,E,1.858,17.98,130110,,,A*54

      上面的每一行称为一个GPS语句,一个完整的语句以$符开始,以换行符结束。其中*符号之后的是校验值,这个值是前面各字符的异或和。我们要实现简单的定位的话,只需要使用上面的一种就可以了。Gemfield选取的是$GPRMC语句,RMC语句是Recommended Minimum data的缩写,意思是推荐的最小定位信息,短小精悍吧。下面来看看这个语句的格式:
$GPRMC,hhmmss,status,latitude,N,longitude,E,spd,cog,ddmmyy,mv,mvE,mode*cs<CR><LF>

      这个语句包含了如下信息:
<1> UTC时间,hhmmss(时分秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4> 纬度半球N(北半球)或S(南半球)
<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,前面的0也将被传输)
<8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
<9> UTC日期,ddmmyy(日月年)格式
<10> 磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
其它更详细的语句信息参考http://www.civilnet.cn/bbs/browse.php?topicno=3490

      下面开始gemfield的Qt程序设计之旅:

      首先我们还是要使用SYSZUX OS提供的串口类,你也可以使用其它的,只要原理类似就可以了。

void gemfieldGps::on_serialport_readyRead()

      int n = serialport->bytesAvailable();//可读的字节个数,一看就是QIODevice的后代
      if(n<=0)
        return; //没有收到信息的话就返回,结束当前的方法体
      gemfield_gps+=serialport->read(n);//gemfield_gps是QbyteArray类型,获得当前串口的完整信息
      if(gemfield_gps.contains("$GPRMC"))//我们选取的是RMC语句,所以我们要筛选出来RMC的帧
    {
        gemfield_gps.remove(0,gemfield_gps.indexOf(gemfield_flag));//去掉$GPRMC之前的暂时不用的信息
        if(gemfield_gps.contains("*"))
           {
              gemfield_rmc=gemfield_gps.left(gemfield_gps.indexOf("*"));//获得除了校验值之外的完整的RMC语句
              QList<QByteArray> gemfield_list=gemfield_rmc.split(',');//分割提取每个语句段
              lcdNumber_2->display(gemfield_list[3].toFloat());//显示纬度信息
              gemfield_gps.clear();//清空gemfield_gps,为下一秒的读取做准备
           }
    }

      上面gemfield并没有采取校验,原因是?呵呵。

      Qt在处理字符串、字节数组方面还是有很多方法可供使用的。现在gemfield的SYSZUX PAD通过串口获得的GPS数据已经能实时显示gemfield的经纬度和时间信息了,所以也可以这么说,gemfield 的SYSZUX PAD 上显示的时间不是当前系统时间,而是美国的GPS授时

http://www.civilnet.cn/blog/browse.php?operation=display&authorno=1&entryno=367&type=blog

posted @ 2011-03-15 12:06  淡茶gis  阅读(1994)  评论(0编辑  收藏  举报