GNSS流程

## 1.测试条件 - 全天空环境,GNSS 天线上方无遮挡,模组上电初始化成功,显示以下信息 ```` +POWERON:0 //正常上电 ^SIMST:1 //检测到 SIM 卡 +CGAPNRC:0,0,0,0,0 +CGEV:ME PDN ACT 0//激活 PDP 成功 +CTZEU:+32,0,2020/10/16,06:40:53//上报时区信息 ```` ## 2.启动GNSS ```` AT+AMGNSSC=1//启动GPS功能 OK ```` ## 3.得到GPS数据 ``` AT+AMGNSSRD? $GNGGA,062721.000,3803.57078,N,11430.32845,E,1,05,10.8,77.4,M,-16.0,M,,*6A $GNGLL,3803.57078,N,11430.32845,E,062721.000,A,A*4D $GNGSA,A,3,10,13,15,20,27,,,,,,,,11.8,10.8,4.7,1*33 $GNGSA,A,3,,,,,,,,,,,,,11.8,10.8,4.7,4*36 $GPGSV,2,1,08,05,14,107,,10,19,301,29,13,28,050,23,15,61,039,37,0*69 $GPGSV,2,2,08,20,45,310,38,21,60,269,,24,55,159,,27,06,313,25,0*61 $BDGSV,1,1,00,0*74 $GNRMC,062721.000,A,3803.57078,N,11430.32845,E,0.00,170.93,231019,,,A,V*04 $GNVTG,170.93,T,,M,0.00,N,0.00,K,A*2F OK AT+AMGNSSRD=”NMEA/RMC” //读取RMC语句 $GNRMC,083435.000,A,3803.82643,N,11430.27742,E,0.00,0.00,110619,,,A,V*0D OK AT+AMGNSSC=0 //关闭GNSS OK ```` ## 4.获取数据函数示例 ```language ********************************************************************************************************* * 函 数 名: gpsGPRMC * 功能说明: 分析0183数据包中的 $GNRMC 命令,结果存放到全局变量 * 形 参: _ucaBuf 收到的数据 * _usLen 数据长度 * 返 回 值: 无 ********************************************************************************************************* */ void gpsGPRMC(uint8_t *_ucaBuf, uint16_t _usLen) { char *p; p = (char *)_ucaBuf; p[_usLen] = 0; /* 字段1 UTC时间,hhmmss.sss格式 */ p = strchr(p, ','); if (p == 0) { return; } p++; g_tGPS.Hour = StrToIntFix(p, 2); p += 2; g_tGPS.Min = StrToIntFix(p, 2); p += 2; g_tGPS.Sec = StrToIntFix(p, 2); p += 3; g_tGPS.mSec = StrToIntFix(p, 3); /* 字段2 状态,A=定位,V=未定位 */ p = strchr(p, ','); if (p == 0) { return; } p++; if (*p != 'A') { /* 未定位则直接返回 */ g_tGPS.PositionOk = 0; return; } g_tGPS.PositionOk = 1; p += 1; /* 字段3 纬度ddmm.mmmm,度分格式(前导位数不足则补0) */ p = strchr(p, ','); if (p == 0) { return; } p++; g_tGPS.WeiDu_Du = StrToIntFix(p, 2); p += 2; g_tGPS.WeiDu_Fen = StrToIntFix(p, 2) * 100000; p += 3; g_tGPS.WeiDu_Fen += StrToIntFix(p, 5); p += 5; /* 字段4 纬度N(北纬)或S(南纬)*/ p = strchr(p, ','); if (p == 0) { return; } p++; if (*p == 'S') { g_tGPS.NS = 'S'; } else if (*p == 'N') { g_tGPS.NS = 'N'; } else { return; } /* 字段5 经度dddmm.mmmm,度分格式(前导位数不足则补0) */ p = strchr(p, ','); if (p == 0) { return; } p++; g_tGPS.JingDu_Du = StrToIntFix(p, 3); p += 3; g_tGPS.JingDu_Fen = StrToIntFix(p, 2) * 100000; p += 3; g_tGPS.JingDu_Fen += StrToIntFix(p, 5); p += 5; /* 字段6:经度E(东经)或W(西经) */ p = strchr(p, ','); if (p == 0) { return; } p++; if (*p == 'E') { g_tGPS.EW = 'E'; } else if (*p == 'W') { g_tGPS.EW = 'W'; } /* 字段7:速度,节,Knots 10.05,*/ p = strchr(p, ','); if (p == 0) { return; } p++; g_tGPS.SpeedKnots = StrToInt(p); /* 字段8:方位角,度 ,324.27 */ p = strchr(p, ','); if (p == 0) { return; } p++; g_tGPS.TrackDegTrue = StrToInt(p); /* 字段9:UTC日期,DDMMYY格式 150706 */ p = strchr(p, ','); if (p == 0) { return; } p++; g_tGPS.Day = StrToIntFix(p, 2); p += 2; g_tGPS.Month = StrToIntFix(p, 2); p += 2; g_tGPS.Year = StrToIntFix(p, 2); p += 2; } ```` 模组得到的GPS经纬度格式如下: 纬度: 38 03.57078 度 分 经度:114 30.32845 度 分 有一些软件地图格式不支持度分格式,只支持度秒格式,度秒格式转换如下:分/60+度.小数点保留后6位四舍五入。 函数示例: ```language ********************************************************************************************************* * 函 数 名: gps_FenToDu * 功能说明: 将分转换为度的小数部分,保留6位小数。 将分换算为度。 * 形 参: 无 * 返 回 值: 返回度的小数部分(十进制) ********************************************************************************************************* */ uint32_t gps_FenToDu(uint32_t _fen) { uint32_t du; /* g_tGPS.WeiDu_Fen; 纬度,分. 232475; 小数点后4位 表示 23.2475分 */ du = (_fen * 100) / 60; return du; } ``` 模组得到GPS的UTC时间格式 时间格式: hh mm ss.sss, 时 分 秒 日期格式: dd mm yy 日 月 年 UTC时间与北京时间时差8小时,注意格式转换,UTC时间hh+8=北京时间 (大于24h注意进位) 函数示例: ```language /* ********************************************************************************************************* 函 数 名: UTCDate * 功能说明: 处理UTC时差 * 形 参: * 返 回 值: ********************************************************************************************************* */ void UTCDate(void) { { uint8_t ucaDays[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (g_tParam.iUTCtime > 0) { g_tGPS.Hour += g_tParam.iUTCtime; if (g_tGPS.Hour > 23) { g_tGPS.Hour = g_tGPS.Hour - 24; g_tGPS.ucDay++; /* 闰年2月份为29天 */ if (IsLeapYear(g_tGPS.usYear)) { ucaDays[1] = 29; } else { ucaDays[1] = 28; } if (g_tGPS.ucDay > ucaDays[g_tGPS.ucMonth - 1]) { g_tGPS.ucDay = 1; g_tGPS.ucMonth++; if (g_tGPS.ucMonth > 12) { g_tGPS.usYear++; } } } } else if (g_tParam.iUTCtime < 0) { int iHour; iHour = g_tGPS.Hour; iHour += g_tParam.iUTCtime; if (iHour < 0) { g_tGPS.Hour = 24 + iHour; if (g_tGPS.ucDay == 1) { if (g_tGPS.ucMonth == 1) { g_tGPS.usYear--; g_tGPS.ucMonth = 12; g_tGPS.ucDay = 31; } else { if (g_tGPS.ucMonth == 3) { g_tGPS.ucMonth = 2; /* 闰年2月份为29天 */ if (IsLeapYear(g_tGPS.usYear)) { g_tGPS.ucDay = 29; } else { g_tGPS.ucDay = 28; } } else { g_tGPS.ucMonth--; g_tGPS.ucDay = ucaDays[g_tGPS.ucMonth]; } } } else { g_tGPS.ucDay--; } } else { g_tGPS.Hour = iHour; } } } #endif } ```