#include #include typedef struct { int hh; int mm; int ss; int sss; }UTCtimeStruct_ts; typedef struct { /*1*/char ID[5]; //消息 ID,GGA 语句头,’--‘为系统标识 /*2*/UTCtimeStruct_ts UTCtime; //hhmmss.sss 当前定位的 UTC 时间 /*3*/float lat; //ddmm.mmmm 纬度,前 2 字符表示度,后面的字符表示分 /*4*/char uLat; //字符 纬度方向:N-北,S-南 /*5*/float lon; //dddmm.mmmm 经度,前 3 字符表示度,后面的字符表示分 /*6*/char uLon; //字符 经度方向:E-东,W-西 /*7*/int FS; //数值 指示当前定位质量(备注[1]),该字段不应为空 // 定位质量标志 描述 // 0 定位不可用或无效 // 1 SPS 定位模式,定位有效 // 6 估算模式(航位推算)仅 NMEA 2.3 及以上版本有效 /*8*/int numSv; //数值 用于定位的卫星数目,00~24 /*9*/float HDOP; //数值 水平精度因子(HDOP) /*10*/float msl; //数值 海拔高度,即接收机天线相对于大地水准面的高度 /*11*/char uMsl; //字符 高度单位,米,固定字符 M /*12*/float sep; //数值 参考椭球面与大地水准面之间的距离,“-”表示大地水准面低于参考椭球面 /*13*/char uSep; //字符 高度单位,米,固定字符 M /*14*/int diffAge; //数值 差分修正的数据龄期,未使用DGPS 时该域为空 /*15*/int diffSta; //数值 差分参考站的 ID /*16*/int CS; //校验和,$和*之间(不包括$和*)所有字符的异或结果 }GPGGA_Struct_ts; typedef struct { /*1*/char ID[5]; //消息 ID,GGA 语句头,’--‘为系统标识 /*2*/float lat; //ddmm.mmmm 纬度,前 2 字符表示度,后面的字符表示分 /*3*/char uLat; //字符 纬度方向:N-北,S-南 /*4*/float lon; //dddmm.mmmm 经度,前 3 字符表示度,后面的字符表示分 /*5*/char uLon; //字符 经度方向:E-东,W-西 /*6*/UTCtimeStruct_ts UTCtime; //hhmmss.sss 当前定位的 UTC 时间 /*7*/char valid; //字符 数据有效性(备注[1]) // 备注[1]数据有效性标志 // 定位质量标志 描述 // A 数据有效 // V 数据无效 /*8*/char mode; //字符 定位模式(备注[2]),仅 NMEA 2.3 及以上版本有效 // 备注[2]定位模式标志 // 定位模式标志 描述 // A 自主模式 // E 估算模式(航位推算) // N 数据无效 // D 差分模式 // M 未定位,但存在外部输入或历史保存的位置 /*9*/int CS; //校验和,$和*之间(不包括$和*)所有字符的异或结果 }GPGLL_Struct_ts; typedef struct { /*1*/char ID[5]; //消息 ID,GGA 语句头,’--‘为系统标识 /*2*/float cogt; //数值 对地真北航向,单位为度 /*3*/char T; //字符 真北指示,固定为 T /*4*/float cogm; // 数值 对地磁北航向,单位为度 /*5*/char M; //字符 磁北指示,固定为 M /*6*/float sog; // 数值 对地速度,单位为节 /*7*/char N; //字符 速度单位节,固定为 N /*8*/float kph; // 数值 对地速度,单位为千米每小时 /*9*/char K; //字符 速度单位,千米每小时,固定为K /*10*/char mode; // 字符 定位模式标志(备注[1])仅 NMEA 2.3 及以上版本有效 // 备注[1]定位模式标志 // 定位模式标志 描述 // A 自主模式 // E 估算模式(航位推算) // N 数据无效 // D 差分模式 // M 未定位,但存在外部输入或历史保存的位置 /*11*/int CS; //校验和,$和*之间(不包括$和*)所有字符的异或结果 }GPVTG_Struct_ts; typedef struct { /*1*/char ID[5]; //消息 ID,GGA 语句头,’--‘为系统标识 /*2*/UTCtimeStruct_ts UTCtime; //hhmmss.sss 定位时的 UTC 时间 /*3*/int day; //数值 日,固定两位数字,取值范围01~31 /*4*/int month; //数值 月,固定两位数字,取值范围01~12 /*5*/int year; //数值 年,固定四位数字 /*6*/int ltzh; //数值 本时区小时,不支持,固定为00 /*7*/int ltzn; //数值 本时区分钟,不支持,固定为00 /*8*/int CS; //校验和,$和*之间(不包括$和*)所有字符的异或结果 }GPZDA_Struct_ts; typedef struct { /*1*/char ID[5]; //消息 ID,GGA 语句头,’--‘为系统标识 /*2*/UTCtimeStruct_ts UTCtime; //hhmmss.sss 当前时刻的 UTC 时间 /*3*/float speed3D; //数值 接收机三维速度,单位为 m/s /*4*/float spdX; //数值 接收机 ECEF-X 轴方向速度,单位为m/s /*5*/float spdY; //数值 接收机 ECEF-Y 轴方向速度,单位为m/s /*6*/float spdZ; //数值 接收机 ECEF-Z 轴方向速度,单位为m/s /*7*/float gdspd; //数值 接收机水平地面方向速度,单位为m/s /*8*/int CS; //校验和,$和*之间(不包括$和*)所有字符的异或结果 }GNDHV_Struct_ts; typedef struct __AT_COMMAND_STRUCT { // uint16_t index; //命令在列表中的序号 char *sscanFmt; // char *printfFmt; // char *cmdHead; // char *cmdInfor; //命令注释说明 }gnssStruct_ts; gnssStruct_ts gnssStructList[] = { { .cmdHead = "$GPGGA", // 1 [ 2 ] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 .sscanFmt = "$%5s,%2d%2d%2d.%3d,%f,%c,%f,%c,%d,%2d,%f,%f,%c,%f,%c,%d,%d*%X\r\n", .printfFmt = "ID = %s,\nUTCtime : hh:%d mm:%d ss:%d .sss:%03d,\nlat = %.4f,\nuLat = %c,\nlon = %.4f,\nuLon = %c,\nFS = %d,\nnumSv = %02d,\nHDOP = %f,\nmsl = %f,\nuMsl = %c,\nsep = %f,\nuSep = %c,\ndiffAge = %d,\ndiffSta = %d,\nCS = %d\n", .cmdInfor = "接收机时间、位置及定位相关的数据", }, { .cmdHead = "$GPGLL", // 1 2 3 4 5 [ 6 ] 7 8 9 .sscanFmt = "$%5s,%f,%c,%f,%c,%2d%2d%2d.%3d,%c,%c*%X\r\n", .printfFmt = "ID = %s,\nlat = %.4f,\nuLat = %c,\nlon = %.4f,\nuLon = %c,\nUTCtime : hh:%d mm:%d ss:%d .sss:%03d,\nvalid = %c,\nmode = %c,\nCS = %d\n", .cmdInfor = "纬度、经度、定位时间与定位状态等信息", }, { .cmdHead = "$GPVTG", // "$GPVTG,75.20,T,0.1,M,0.009,N,0.017,K,A*02" // 1 2 3 4 5 6 7 8 9 10 11 .sscanFmt = "$%5s,%f,%c,%[^,],%c,%f,%c,%f,%c,%c*%X\r\n", .printfFmt = "ID = %s,\ncogt = %f,\nT = %c,\ncogm = %f,\nM = %c,\nsog = %f,\nN = %c,\nkph = %f,\nK = %c,\nmode = %c,\nCS = %d\n", .cmdInfor = "对地速度与对地航向信息", }, { .cmdHead = "$GPZDA", // 1 [ 2 ] 3 4 5 6 7 8 .sscanFmt = "$%5s,%2d%2d%2d.%3d,%d,%d,%d,%d,%d*%X\r\n", .printfFmt = "ID = %s,\nUTCtime : hh:%d mm:%d ss:%d .sss:%03d,\nday = %02d,\nmonth = %02d,\nyear = %04d,\nltzh = %02d,\nltzn = %02d,\nCS = %d\n", .cmdInfor = "时间与日期信息", }, { .cmdHead = "$GNDHV", // 1 [ 2 ] 3 4 5 6 7 8 .sscanFmt = "$%5s,%2d%2d%2d.%3d,%f,%f,%f,%f,%f*%X\r\n", .printfFmt = "ID = %s,\nUTCtime : hh:%d mm:%d ss:%d .sss:%03d,\nspeed3D = %f,\nspdX = %f,\nspdY = %f,\nspdZ = %f,\ngdspd = %f,\nCS = %d\n", .cmdInfor = "接收机速度的详细信息", }, }; GPGGA_Struct_ts GPGGA_Struct; GPGLL_Struct_ts GPGLL_Struct; GPVTG_Struct_ts GPVTG_Struct; GPZDA_Struct_ts GPZDA_Struct; GNDHV_Struct_ts GNDHV_Struct; char* _strtok(char *s, const char *delim) { const char *spanp; int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) { // printf("no char1000 s == NULL"); return (NULL); } /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). * 跳过字符串首部的分隔符 */ int rcount = 0; cont: c = *s++; for (spanp = delim;(sc = *spanp++) != 0; ) { if (c == sc) { s[-1] = 0; last = s; return (NULL); // goto cont; } } /* *分割符后面没有字符串了 */ if (c == 0) { /* no non-delimiter characters */ last = NULL; // printf("no char1000"); return (NULL); } tok = s - 1;/*分割符后面还有字符串,将tok指向字符串首部(不包括分隔符)*/ /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL;we stop if we see that, too. * 循环字符串中的字符,直到找到分隔符或者结束符,并替换成结束符 */ rcount = 0; for(;;) { c = *s++; spanp = delim; /* *判断字符串中的某字符是不是分割符中的字符 *若是是,将分隔符替换成结束符并返回tok; *若是不是,继续判断下一个字符 */ do { if ((sc = *spanp++) == c) { if (c == 0) { s = NULL; } else { s[-1] = 0; } last = s; return (tok); } // if(rcount ++ > 100) // { // printf("no char1000"); // break; // } } while (sc != 0); } /* NOTREACHED */ return NULL; } char* mystrtok(char *s, const char *delim) { const char *spanp; int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) { printf("no char1000 s == NULL"); return (NULL); } /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). * 跳过字符串首部的分隔符 */ int rcount = 0; cont: c = *s++; for (spanp = delim;(sc = *spanp++) != 0; ) { if(rcount ++ > 100) { printf("no char1000"); break; } if (c == sc) goto cont; } /* *分割符后面没有字符串了 */ if (c == 0) { /* no non-delimiter characters */ last = NULL; printf("no char1000"); return (NULL); } tok = s - 1;/*分割符后面还有字符串,将tok指向字符串首部(不包括分隔符)*/ /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL;we stop if we see that, too. * 循环字符串中的字符,直到找到分隔符或者结束符,并替换成结束符 */ rcount = 0; for(;;) { c = *s++; spanp = delim; /* *判断字符串中的某字符是不是分割符中的字符 *若是是,将分隔符替换成结束符并返回tok; *若是不是,继续判断下一个字符 */ do { if ((sc = *spanp++) == c) { if (c == 0) { s = NULL; printf("no s = NULL\n"); } else { if(s != NULL) s[-1] = 0; else return NULL; } printf("no char %d %d\n", last, s); last = s; return (tok); } if(rcount ++ > 100) { printf("no char1000"); break; } } while (sc != 0); } printf("no char"); /* NOTREACHED */ return NULL; } void GPGGA_sscanf(char *src) { char str[255]; const char s[2] = ","; char *token; char *replaceAddr; int count = 0; memset(str, 0, sizeof(str)); memcpy(str, src, strlen(src)); replaceAddr = strstr(str, "*"); if (replaceAddr) { *replaceAddr = ','; } printf(str); /* 获取第一个子字符串 */ token = _strtok(str, s); /* 继续获取其他的子字符串 */ while(count <= 15) { // printf( "token = %s ,count=%d\n", token,count ); if(token != NULL) { switch(count) { case 0: { sscanf(token, "$%5s", GPGGA_Struct.ID); }break; case 1: { sscanf(token, "%2d%2d%2d.%3d", &GPGGA_Struct.UTCtime.hh,&GPGGA_Struct.UTCtime.mm,&GPGGA_Struct.UTCtime.ss,&GPGGA_Struct.UTCtime.sss); }break; case 2: { sscanf(token, "%f", &GPGGA_Struct.lat); }break; case 3: { sscanf(token, "%c", &GPGGA_Struct.uLat); }break; case 4: { sscanf(token, "%f", &GPGGA_Struct.lon); }break; case 5: { sscanf(token, "%c", &GPGGA_Struct.uLon); }break; case 6: { sscanf(token, "%d", &GPGGA_Struct.FS); }break; case 7: { sscanf(token, "%d", &GPGGA_Struct.numSv); }break; case 8: { sscanf(token, "%f", &GPGGA_Struct.HDOP); }break; case 9: { sscanf(token, "%f", &GPGGA_Struct.msl); }break; case 10: { sscanf(token, "%c", &GPGGA_Struct.uMsl); }break; case 11: { sscanf(token, "%f", &GPGGA_Struct.sep); }break; case 12: { sscanf(token, "%c", &GPGGA_Struct.uSep); }break; case 13: { sscanf(token, "%d", &GPGGA_Struct.diffAge); }break; case 14: { sscanf(token, "%d", &GPGGA_Struct.diffSta); }break; case 15: { sscanf(token, "%X", &GPGGA_Struct.CS); }break; default: break; } } token = _strtok(NULL, s); count ++; } } void GPGLL_sscanf(char *src) { char str[255]; const char s[2] = ","; char *token; char *replaceAddr; int count = 0; memset(str, 0, sizeof(str)); memcpy(str, src, strlen(src)); replaceAddr = strstr(str, "*"); if (replaceAddr) { *replaceAddr = ','; } printf(str); /* 获取第一个子字符串 */ token = _strtok(str, s); /* 继续获取其他的子字符串 */ while(count <= 8) { // printf( "token = %s ,count=%d\n", token,count ); if(token != NULL) { switch(count) { case 0: { sscanf(token, "$%5s", GPGLL_Struct.ID); }break; case 1: { sscanf(token, "%f", &GPGLL_Struct.lat); }break; case 2: { sscanf(token, "%c", &GPGLL_Struct.uLat); }break; case 3: { sscanf(token, "%f", &GPGLL_Struct.lon); }break; case 4: { sscanf(token, "%c", &GPGLL_Struct.uLon); }break; case 5: { sscanf(token, "%2d%2d%2d.%3d", &GPGLL_Struct.UTCtime.hh,&GPGLL_Struct.UTCtime.mm,&GPGLL_Struct.UTCtime.ss,&GPGLL_Struct.UTCtime.sss); }break; case 6: { sscanf(token, "%c", &GPGLL_Struct.valid); }break; case 7: { sscanf(token, "%c", &GPGLL_Struct.mode); }break; case 8: { sscanf(token, "%X", &GPGLL_Struct.CS); }break; default: break; } } token = _strtok(NULL, s); count ++; } } void GPVTG_sscanf(char *src) { char str[255]; const char s[2] = ","; char *token; char *replaceAddr; int count = 0; memset(str, 0, sizeof(str)); memcpy(str, src, strlen(src)); replaceAddr = strstr(str, "*"); if (replaceAddr) { *replaceAddr = ','; } printf(str); /* 获取第一个子字符串 */ token = _strtok(str, s); /* 继续获取其他的子字符串 */ while(count <= 10) { // printf( "token = %s ,count=%d\n", token,count ); if(token != NULL) { switch(count) { case 0: { sscanf(token, "$%5s", GPVTG_Struct.ID); }break; case 1: { sscanf(token, "%f", &GPVTG_Struct.cogt); }break; case 2: { sscanf(token, "%c", &GPVTG_Struct.T); }break; case 3: { sscanf(token, "%f", &GPVTG_Struct.cogm); }break; case 4: { sscanf(token, "%c", &GPVTG_Struct.M); }break; case 5: { sscanf(token, "%f", &GPVTG_Struct.sog); }break; case 6: { sscanf(token, "%c", &GPVTG_Struct.N); }break; case 7: { sscanf(token, "%f", &GPVTG_Struct.kph); }break; case 8: { sscanf(token, "%c", &GPVTG_Struct.K); }break; case 9: { sscanf(token, "%c", &GPVTG_Struct.mode); }break; case 10: { sscanf(token, "%X", &GPVTG_Struct.CS); }break; default: break; } } token = _strtok(NULL, s); count ++; } } void GPZDA_sscanf(char *src) { char str[255]; const char s[2] = ","; char *token; char *replaceAddr; int count = 0; memset(str, 0, sizeof(str)); memcpy(str, src, strlen(src)); replaceAddr = strstr(str, "*"); if (replaceAddr) { *replaceAddr = ','; } printf(str); /* 获取第一个子字符串 */ token = _strtok(str, s); /* 继续获取其他的子字符串 */ while(count <= 7) { // printf( "token = %s ,count=%d\n", token,count ); if(token != NULL) { switch(count) { case 0: { sscanf(token, "$%5s", GPZDA_Struct.ID); }break; case 1: { sscanf(token, "%2d%2d%2d.%3d", &GPZDA_Struct.UTCtime.hh,&GPZDA_Struct.UTCtime.mm,&GPZDA_Struct.UTCtime.ss,&GPZDA_Struct.UTCtime.sss); }break; case 2: { sscanf(token, "%d", &GPZDA_Struct.day); }break; case 3: { sscanf(token, "%d", &GPZDA_Struct.month); }break; case 4: { sscanf(token, "%d", &GPZDA_Struct.year); }break; case 5: { sscanf(token, "%d", &GPZDA_Struct.ltzh); }break; case 6: { sscanf(token, "%d", &GPZDA_Struct.ltzn); }break; case 7: { sscanf(token, "%X", &GPZDA_Struct.CS); }break; default: break; } } token = _strtok(NULL, s); count ++; } } void GNDHV_sscanf(char *src) { char str[255]; const char s[2] = ","; char *token; char *replaceAddr; int count = 0; memset(str, 0, sizeof(str)); memcpy(str, src, strlen(src)); replaceAddr = strstr(str, "*"); if (replaceAddr) { *replaceAddr = ','; } printf(str); /* 获取第一个子字符串 */ token = _strtok(str, s); /* 继续获取其他的子字符串 */ while(count <= 7) { // printf( "token = %s ,count=%d\n", token,count ); if(token != NULL) { switch(count) { case 0: { sscanf(token, "$%5s", GNDHV_Struct.ID); }break; case 1: { sscanf(token, "%2d%2d%2d.%3d", &GNDHV_Struct.UTCtime.hh,&GNDHV_Struct.UTCtime.mm,&GNDHV_Struct.UTCtime.ss,&GNDHV_Struct.UTCtime.sss); }break; case 2: { sscanf(token, "%f", &GNDHV_Struct.speed3D); }break; case 3: { sscanf(token, "%f", &GNDHV_Struct.spdX); }break; case 4: { sscanf(token, "%f", &GNDHV_Struct.spdY); }break; case 5: { sscanf(token, "%f", &GNDHV_Struct.spdZ); }break; case 6: { sscanf(token, "%f", &GNDHV_Struct.gdspd); }break; case 7: { sscanf(token, "%X", &GNDHV_Struct.CS); }break; default: break; } } token = _strtok(NULL, s); count ++; } } void decodeGnss(char *src) { if (strstr(src, "$GPGGA")) { GPGGA_sscanf(src); // GPGGA_sscanf("$GPGGA,235316.000,2959.9925,S,12000.0090,E,1,06,1.21,62.77,,0.00,M,,0*7B"); printf(gnssStructList[0].printfFmt, GPGGA_Struct.ID, GPGGA_Struct.UTCtime.hh,GPGGA_Struct.UTCtime.mm,GPGGA_Struct.UTCtime.ss,GPGGA_Struct.UTCtime.sss, GPGGA_Struct.lat, GPGGA_Struct.uLat, GPGGA_Struct.lon, GPGGA_Struct.uLon, GPGGA_Struct.FS, GPGGA_Struct.numSv, GPGGA_Struct.HDOP, GPGGA_Struct.msl, GPGGA_Struct.uMsl, GPGGA_Struct.sep, GPGGA_Struct.uSep, GPGGA_Struct.diffAge, GPGGA_Struct.diffSta, GPGGA_Struct.CS ); } if (strstr(src, "$GPGLL")) { printf("-------------%d\n"); GPGLL_sscanf(src); // GPGLL_sscanf("$GPGLL,2959.9925,A,12000.0090,E,235316.000,A,A*4E"); printf(gnssStructList[1].printfFmt, GPGLL_Struct.ID, GPGLL_Struct.lat, GPGLL_Struct.uLat, GPGLL_Struct.lon, GPGLL_Struct.uLon, GPGLL_Struct.UTCtime.hh,GPGLL_Struct.UTCtime.mm,GPGLL_Struct.UTCtime.ss,GPGLL_Struct.UTCtime.sss, GPGLL_Struct.valid, GPGLL_Struct.mode, GPGLL_Struct.CS ); } if (strstr(src, "$GPVTG")) { printf("-------------\n"); GPVTG_sscanf(src); // GPVTG_sscanf("$GPVTG,75.20,T,,M,0.009,N,0.017,K,A*02"); printf(gnssStructList[2].printfFmt, GPVTG_Struct.ID, GPVTG_Struct.cogt, GPVTG_Struct.T, GPVTG_Struct.cogm, GPVTG_Struct.M, GPVTG_Struct.sog, GPVTG_Struct.N, GPVTG_Struct.kph, GPVTG_Struct.K, GPVTG_Struct.mode, GPVTG_Struct.CS ); } if (strstr(src, "$GPZDA")) { printf("-------------\n"); GPZDA_sscanf(src); // GPZDA_sscanf("$GPZDA,235316.000,02,07,2011,00,00*51"); printf(gnssStructList[3].printfFmt, GPZDA_Struct.ID, GPZDA_Struct.UTCtime.hh,GPZDA_Struct.UTCtime.mm,GPZDA_Struct.UTCtime.ss,GPZDA_Struct.UTCtime.sss, GPZDA_Struct.day, GPZDA_Struct.month, GPZDA_Struct.year, GPZDA_Struct.ltzh, GPZDA_Struct.ltzn, GPZDA_Struct.CS ); } if (strstr(src, "$GNDHV")) { printf("-------------\n"); GNDHV_sscanf(src); // GNDHV_sscanf("$GNDHV,021150.000,0.03,0.006,-0.042,-0.026,0.06*65"); printf(gnssStructList[4].printfFmt, GNDHV_Struct.ID, GNDHV_Struct.UTCtime.hh,GNDHV_Struct.UTCtime.mm,GNDHV_Struct.UTCtime.ss,GNDHV_Struct.UTCtime.sss, GNDHV_Struct.speed3D, GNDHV_Struct.spdX, GNDHV_Struct.spdY, GNDHV_Struct.spdZ, GNDHV_Struct.gdspd, GNDHV_Struct.CS ); } }