nmea.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. #include "nmea.h"
  2. #ifndef NULL
  3. #define NULL '\0'
  4. #endif
  5. NMEA_DEF nmeaInfo={
  6. .isGpsValid=0
  7. };
  8. /*
  9. str串以\r\n或\r或\n结尾,以此为标志截断
  10. */
  11. void turncateStr(char *str){
  12. int i;
  13. for(i=0;i<strlen(str);i++){
  14. if(str[i]=='\r' || str[i]=='\n'){
  15. str[i]=0;
  16. return;
  17. }
  18. }
  19. }
  20. /*
  21. nmea为原始数据,所有字段串在一起
  22. 这里预处理一下,提取target字段
  23. */
  24. char * preNmea(char *nmea, char *target){
  25. int i;
  26. char *ret;
  27. if(nmea==NULL) return NULL;
  28. ret=strstr(nmea,target);
  29. if(NULL!=ret) turncateStr(ret);
  30. return ret;
  31. }
  32. #define GPS_TYPE_ZKW
  33. #define GPS_TYPE_UBLOX
  34. #define GPRMC_UTC1_TOKEN_INDEX 0
  35. #define GPRMC_STATUS_TOKEN_INDEX 1
  36. #define GPRMC_LATITUE_TOKEN_INDEX 2
  37. #define GPRMC_NORTH_TOKEN_INDEX 3
  38. #define GPRMC_longitue_TOKEN_INDEX 4
  39. #define GPRMC_EAST_TOKEN_INDEX 5
  40. #define GPRMC_SPEED_TOKEN_INDEX 6
  41. #define GPRMC_ASPECT_TOKEN_INDEX 7
  42. #define GPRMC_UTC2_TOKEN_INDEX 8
  43. /*
  44. 解析RMC字段并获取相关值
  45. */
  46. void nmeaRmc(char *rmc)
  47. {
  48. unsigned int size=strlen(rmc);
  49. char tmp_char[16] = {0};
  50. char bcd_tmp[8] = {0};
  51. char *token[16] = {NULL};
  52. char size_each_token[16] = {0};
  53. unsigned char hh,hl;
  54. unsigned char token_index = 0;
  55. char ch;
  56. int i = 0;
  57. int index = 0;
  58. int dig_bit_num = 0;
  59. int ptr_each = 0;
  60. unsigned short speed;
  61. unsigned short aspect;
  62. double speed_jie = 0.0;
  63. token[token_index] = rmc;
  64. while(index < size )
  65. {
  66. if(rmc[index] == ',')
  67. {
  68. size_each_token[token_index] = ptr_each;
  69. if(ptr_each == 0)
  70. token[token_index] = NULL;
  71. ptr_each = 0;
  72. token_index++;
  73. token[token_index] = rmc+index+1; //skip this ','
  74. if(*(token[token_index]+1) == '*')
  75. {
  76. size_each_token[token_index] = 1; //cut of *hh\r\n
  77. }
  78. }
  79. else
  80. {
  81. ptr_each++;
  82. }
  83. index++;
  84. }
  85. //UTC time:hms
  86. //014216 = 01:42:16
  87. #if 0 //»ñÈ¡GPSʱ¼ä
  88. if(token[GPRMC_UTC1_TOKEN_INDEX])
  89. { //,040831.00, Ò»°ã³¤¶ÈΪ9
  90. if(size_each_token[0]<6 && size_each_token[0]>10){
  91. //printf("GPS Error1 %d\r\n",size_each_token[0]);
  92. return;
  93. }
  94. strncpy((char*)tmp_char,(char*)token[0],size_each_token[0]);
  95. translate_digitAscii_to_bcd(tmp_char,6,bcd_tmp); //??.xx
  96. nmeaInfo.hour=bcd_tmp[0];
  97. nmeaInfo.minu = bcd_tmp[1];
  98. nmeaInfo.sec = bcd_tmp[2];
  99. }
  100. //UTC2
  101. //250219 = 19-02-25
  102. if(token[GPRMC_UTC2_TOKEN_INDEX])
  103. {
  104. memset(tmp_char , 0 ,sizeof(tmp_char));
  105. memset(bcd_tmp , 0 ,sizeof(bcd_tmp));
  106. if(size_each_token[GPRMC_UTC2_TOKEN_INDEX]!=6){
  107. //printf("GPS Error2\r\n");
  108. return;
  109. }
  110. strncpy((char*)tmp_char,(char*)token[GPRMC_UTC2_TOKEN_INDEX],size_each_token[GPRMC_UTC2_TOKEN_INDEX]);
  111. translate_digitAscii_to_bcd(tmp_char,6,bcd_tmp);
  112. nmeaInfo.day = bcd_tmp[0];
  113. nmeaInfo.month= bcd_tmp[1];
  114. nmeaInfo.year = bcd_tmp[2];
  115. }
  116. #endif
  117. //Fix status
  118. if(token[GPRMC_STATUS_TOKEN_INDEX])
  119. {
  120. memset(tmp_char , 0 ,sizeof(tmp_char));
  121. if(size_each_token[1]!=1){
  122. //wlog_error("GpsDataError!");
  123. return;
  124. }
  125. strncpy((char*)tmp_char,(char*)token[1],size_each_token[1]);
  126. if(*tmp_char == 'A'){
  127. nmeaInfo.isGpsValid = GPS_ACTIVE;
  128. }else{
  129. nmeaInfo.isGpsValid = GPS_INVALID;
  130. nmeaInfo.Altitude=0;
  131. nmeaInfo.Latitude=0;
  132. nmeaInfo.Longitude=0;
  133. nmeaInfo.Aspect=0;
  134. nmeaInfo.Speed=0;
  135. return;
  136. }
  137. }
  138. //latitude ??
  139. /*=====================================
  140. UTC time:hms status latitue north? longitue east? ??(?) ??? UTC time ??? ?? ?? checksum
  141. $GPRMC hhmmss.ss A/V ddmm.mmmm N/S dddmm.mmmm E/W speed aspect ddmmyy 000-180 E/W A/D/E/N *hh
  142. For example: $GPRMC,024813.640,A,3158.4608,N,11848.3737,E,010.5,324.7,150706,,,A*50
  143. */
  144. if(token[GPRMC_LATITUE_TOKEN_INDEX])
  145. {//ddmm.mmmmm,N/S
  146. ch=*token[GPRMC_NORTH_TOKEN_INDEX];
  147. char *p=token[GPRMC_LATITUE_TOKEN_INDEX];
  148. //ddmm.mmmmm
  149. int ddmm=atoi(p);
  150. int mmmmm=atoi((p+5));
  151. int dd=ddmm/100;
  152. int mm=ddmm%100;
  153. //double fmm=(double)mm+(double)mmmmm/100000.0;
  154. //nmeaInfo.latitude=(double)dd+fmm/60.0;
  155. nmeaInfo.Latitude=dd*1000000;//¶È ·Å´ó1000000±¶£¬ÕûÊý²¿·Ö
  156. mm*=1000000;
  157. mmmmm*=10;
  158. mm+=mmmmm;//·Ö ·Å´ó1000000±¶
  159. dd=mm/60;//¶È ·Å´ó1000000±¶ СÊý²¿·Ö
  160. nmeaInfo.Latitude+=dd;//¶È ·Å´ó1000000±¶
  161. if(ch=='S'){
  162. nmeaInfo.South=1;
  163. }else{
  164. nmeaInfo.South=0;
  165. }
  166. //sprintf(nmeaInfo.vv1,"%d%d.%d\r\n",dd,mm,mmmm);
  167. }
  168. //longitude ??
  169. if(token[GPRMC_longitue_TOKEN_INDEX])
  170. {//dddmm.mmmmm,E/W
  171. #if 0
  172. memset(tmp_char , 0 ,sizeof(tmp_char));
  173. memset(bcd_tmp , 0 ,sizeof(bcd_tmp));
  174. strncpy((char*)tmp_char,(char*)token[4],size_each_token[4]);
  175. for(i = 5; i < 8;i++)
  176. tmp_char[i] = tmp_char[i+1];
  177. tmp_char[8] = 0;
  178. translate_digitAscii_to_bcd(tmp_char,8,bcd_tmp); //??.xx
  179. //east or west
  180. if(token[GPRMC_EAST_TOKEN_INDEX])
  181. {
  182. memset(tmp_char , 0 ,sizeof(tmp_char));
  183. strncpy((char*)tmp_char,(char*)token[5],size_each_token[5]);
  184. nmeaInfo.EWFlag=*tmp_char;
  185. nmeaInfo.longitude = (bcd_tmp[3] | (bcd_tmp[2] << 8) |(bcd_tmp[1] << 16) |(bcd_tmp[0] << 24));
  186. }
  187. #else
  188. ch=*token[GPRMC_EAST_TOKEN_INDEX];
  189. if(ch=='W')nmeaInfo.West=1;
  190. else nmeaInfo.West=0;
  191. char *p=token[GPRMC_longitue_TOKEN_INDEX];
  192. int dddmm=atoi(p);
  193. int mmmmm=atoi((p+6));
  194. int ddd=dddmm/100;
  195. int mm=dddmm%100;
  196. //double fmm=(double)mm+(double)mmmmm/100000.0;
  197. //nmeaInfo.longitude=(double)ddd+fmm/60.0;
  198. nmeaInfo.Longitude=ddd*1000000;//¶È ·Å´ó1000000±¶ ÕûÊý²¿·Ö
  199. mm*=1000000;
  200. mmmmm*=10;
  201. mm+=mmmmm;//·Ö ·Å´ó1000000±¶
  202. ddd=mm/60;//¶È ·Å´ó1000000±¶ СÊý²¿·Ö
  203. nmeaInfo.Longitude+=ddd;
  204. #endif
  205. }
  206. //Speed
  207. //0.094
  208. if(token[GPRMC_SPEED_TOKEN_INDEX])
  209. {
  210. memset(tmp_char , 0 ,sizeof(tmp_char));
  211. strncpy((char*)tmp_char,(char*)token[GPRMC_SPEED_TOKEN_INDEX],size_each_token[GPRMC_SPEED_TOKEN_INDEX]);
  212. index = 0;
  213. while(index < size_each_token[GPRMC_SPEED_TOKEN_INDEX])
  214. {
  215. if(tmp_char[index] == '.')break;
  216. index++;
  217. }
  218. dig_bit_num = size_each_token[GPRMC_SPEED_TOKEN_INDEX]-index-1;
  219. speed_jie = atoi(tmp_char);
  220. if(dig_bit_num>0)speed_jie += (tmp_char[index+1]-0x30)*0.1;
  221. //nmeaInfo.Speed=(int)(speed_jie/0.1852);// 1/10 km
  222. nmeaInfo.Speed=(int)(speed_jie*18.52);// 1/10 km
  223. //1½ÚÒ²¾ÍÊÇ1.852¹«Àï/Сʱ.
  224. }
  225. //Aspect ??
  226. if(token[GPRMC_ASPECT_TOKEN_INDEX])
  227. {
  228. memset(tmp_char , 0 ,sizeof(tmp_char));
  229. if(size_each_token[GPRMC_ASPECT_TOKEN_INDEX]==0){
  230. nmeaInfo.Aspect=0;
  231. }else{
  232. strncpy((char*)tmp_char,(char*)token[GPRMC_ASPECT_TOKEN_INDEX],size_each_token[GPRMC_ASPECT_TOKEN_INDEX]);
  233. aspect=atoi(tmp_char);
  234. nmeaInfo.Aspect= aspect;
  235. }
  236. }else nmeaInfo.Aspect=0;
  237. }
  238. /*
  239. 解析GSA字段并获取相关值
  240. */
  241. void nmeaGsa(char *gsa){
  242. int size=strlen(gsa);
  243. #if defined GPS_TYPE_UBLOX //---------------------------------UbloxоƬ·½°¸
  244. /*
  245. UbloxÄ£¿é£º
  246. $GNGSA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>,<14>,<15>,<16
  247. <1>ģʽ2:M=ÊÖ¶¯,A=×Ô¶¯
  248. <2>ģʽ1:¶¨Î»ÐÍʽ1=δ¶¨Î»,2=¶þά¶¨Î»,3=Èýά¶¨Î»
  249. <3>µÚ1ÐŵÀÕýÔÚʹÓõÄÎÀÐÇPRNÂë±àºÅ01ÖÁ32(Ç°µ¼Î»Êý²»×ãÔò²¹0,×î¶à¿É½ÓÊÕ12¿ÅÎÀÐÇÐÅÏ¢)
  250. <4>µÚ2ÐŵÀÕýÔÚʹÓõÄÎÀÐÇPRNÂë±àºÅ01ÖÁ32(Ç°µ¼Î»Êý²»×ãÔò²¹0,×î¶à¿É½ÓÊÕ12¿ÅÎÀÐÇÐÅÏ¢)
  251. ...
  252. ¶ÔÓÚ±±¶·£¬PRN±àÂë´Ó401¿ªÊ¼...
  253. ¾ÙÀý£º
  254. $GNGSA,A,3,18,11,31,08,,,,,,,,,3.03,2.13,2.15*19
  255. ÕýÔÚʹÓÃÎÀÐÇ GPS±àºÅΪ18 11 31 08 ¹²4¿ÅÎÀÐÇ£¬ PDOPÒò×ÓΪ3.03
  256. $GNGSA,A,3,416,401,406,408,424,428,,,,,,,3.03,2.13,2.15*1E
  257. ÕýÔÚʹÓÃÎÀÐÇ BD±àºÅΪ416 401 406 408 424 428 ¹²6¿ÅÎÀÐÇ £¬PDOPÒò×ÓΪ3.03
  258. */
  259. int flag=0;
  260. int i,j,k,BDNum,GPSNum,PDOP;
  261. char ch,ch1,ch2;
  262. if(gsa[7]!='A' && gsa[0]!='M' )return;
  263. // if(gsa[9]=='1'){//δ¶¨Î»
  264. // nmeaInfo.GPSNum=0;
  265. // nmeaInfo.BDNum=0;
  266. // nmeaInfo.PDOP=0;
  267. // return;
  268. // }
  269. // if(gsa[9]!='2' && gsa[9]!='3' )return;
  270. i=11;j=0;k=0;BDNum=0;GPSNum=0;
  271. while(i<size && j<12){
  272. ch=gsa[i];
  273. if(ch==','){
  274. i++;
  275. j++;
  276. if(k==2)GPSNum++;
  277. else if(k==3)BDNum++;
  278. k=0;
  279. }else if(ch>='0' && ch<='9'){
  280. i++;
  281. k++;
  282. }else{
  283. break;
  284. }
  285. }
  286. PDOP=0;
  287. if(j==12){
  288. if(gsa[i]>='0' && gsa[i]<='9' && gsa[i+1]=='.' && gsa[i+2]>='0' && gsa[i+2]<='9'){
  289. PDOP=(gsa[i]-0x30);
  290. PDOP*=10;
  291. PDOP+=(gsa[i+2]-0x30);
  292. }
  293. }
  294. if(GPSNum>12)GPSNum=12;
  295. if(BDNum>12)BDNum=12;
  296. if(PDOP>63)PDOP=63;
  297. if(GPSNum>0)nmeaInfo.GPSNum=GPSNum;
  298. if(BDNum>0)nmeaInfo.BDNum=BDNum;
  299. nmeaInfo.PDOP=PDOP;
  300. #elif defined GPS_TYPE_ZKW //---------------------------------ÖпÆ΢оƬ·½°¸
  301. /*
  302. ÖпÆ΢ģ¿é£º
  303. $GPGSA,A,3,33,14,22,27,31,32,08,35,21,,,,1.6,1.1,1.2*38
  304. $BDGSA,A,3,01,02,03,04,08,09,13,06,,,,,1.6,1.1,1.2*26
  305. */
  306. int flag=0;
  307. int i,j,num;
  308. char ch,ch1,ch2;
  309. if(gsa[7]!='A' && gsa[0]!='M' )return;
  310. if(gsa[9]=='1'){//δ¶¨Î»
  311. nmeaInfo.GPSNum=0;
  312. nmeaInfo.BDNum=0;
  313. return;
  314. }
  315. if(gsa[9]!='2' && gsa[9]!='3' )return;
  316. i=11;j=0;num=0;
  317. while(i<size && j<12){
  318. ch=gsa[i];
  319. if(ch==','){
  320. i++;
  321. j++;
  322. }else if(ch>='0' && ch<='9'){
  323. i+=2;
  324. num++;
  325. }else{//·Ç·¨
  326. break;
  327. }
  328. }
  329. PDOP=0;
  330. if(j==12){
  331. if(gsa[i]>='0' && gsa[i]<='9' && gsa[i+1]=='.' && gsa[i+2]>='0' && buf[i+2]<='9'){
  332. PDOP=(gsa[i]-0x30);
  333. PDOP*=10;
  334. PDOP+=(gsa[i+2]-0x30);
  335. }
  336. }
  337. if(GPSNum>12)GPSNum=12;
  338. if(BDNum>12)BDNum=12;
  339. if(PDOP>63)PDOP=63;
  340. if(flag==1){
  341. nmeaInfo.GPSNum=num;
  342. }else if(flag==2){
  343. nmeaInfo.BDNum=num;
  344. }
  345. nmeaInfo.PDOP=PDOP;
  346. #endif
  347. }