歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C語言解碼GPS--實現篇

C語言解碼GPS--實現篇

日期:2017/3/1 10:11:36   编辑:Linux編程

通過自己這幾天的努力終於把GPS數據全部進行了解碼,相信看了我的日志的人也期待了好久,資源在於分享,才能獲得進步;相對於網上直接調用接口不同的是從C的方向解決問題能讓問題更加的清晰,本設計芯片采用的是聯星的CC550-BG模塊,滿足大多數芯片性能,系統是在LINUX系統下面實現,選用ttyS0節點,根據不同借口,串口線選擇的是RS-232,相信大家也有所了解,詳細的請看我代碼,都有詳細的解釋,希望幫到大家,這裡我只解析了GPRMC格式的編碼,大家也可以把其他幾種格式的編碼解析同樣解析出來,只要在read_data()函數裡面strncmp()的array數組改變名稱就可以,可以把他寫成Switch格式的解碼選擇器,好了廢話不多說,貼上我的代碼!

  1. #include <stdio.h> /*標准輸入輸出定義*/
  2. #include <stdlib.h> /*標准函數庫定義*/
  3. #include <unistd.h> /*Unix 標准函數定義*/
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <errno.h>
  7. #include <string.h>
  8. #include <fcntl.h>
  9. #include <termios.h>
  10. //#define dev "/dev/ttyS0"
  11. #define BUFF_SIZE 512
  12. #define MAX_COM_NUM 3
  13. int SectionID=0,i=0;
  14. struct data
  15. {
  16. char GPS_time[20]; //UTC時間
  17. char GPS_sv; //使用衛星
  18. char GPS_wd[12]; //緯度
  19. char GPS_jd[12]; //經度
  20. //char GPS_warn; //定位警告
  21. char GPS_speed[5]; //速度
  22. char GPS_date[8]; //UTC日期
  23. }GPS_DATA;
  24. int set_com_config(int fd,int baud_rate,int data_bits,char parity,int stop_bits)
  25. {
  26. struct termios new_cfg,old_cfg;
  27. int speed;
  28. //保存並測試現有串口參數設置,在這裡如果串口號出錯,會有相關的出錯信息
  29. if(tcgetattr(fd,&old_cfg)!=0)
  30. {
  31. perror("tcgetattr");
  32. return -1;
  33. }
  34. tcflush(fd, TCIOFLUSH);
  35. new_cfg=old_cfg;
  36. cfmakeraw(&new_cfg);//配置為原始模式
  37. new_cfg.c_cflag&=~CSIZE;
  38. //設置波特率
  39. switch(baud_rate)
  40. {
  41. case 2400:
  42. {
  43. speed = B2400;
  44. break;
  45. }
  46. case 4800:
  47. {
  48. speed = B4800;
  49. break;
  50. }
  51. case 9600:
  52. {
  53. speed = B9600;
  54. break;
  55. }
  56. case 19200:
  57. {
  58. speed = B19200;
  59. break;
  60. }
  61. case 38400:
  62. {
  63. speed = B38400;
  64. break;
  65. }
  66. case 115200:
  67. {
  68. speed = B115200;
  69. break;
  70. }
  71. }
  72. cfsetispeed(&new_cfg,speed);
  73. cfsetospeed(&new_cfg,speed);
  74. //設置數據位
  75. switch(data_bits)
  76. {
  77. case 7:
  78. {
  79. new_cfg.c_cflag|=CS7;
  80. break;
  81. }
  82. case 8:
  83. {
  84. new_cfg.c_cflag|=CS8;
  85. break;
  86. }
  87. }
  88. //設置停止位
  89. switch(stop_bits)
  90. {
  91. case 1:
  92. {
  93. new_cfg.c_cflag &=~CSTOPB;
  94. break;
  95. }
  96. case 2:
  97. {
  98. new_cfg.c_cflag |=CSTOPB;
  99. break;
  100. }
  101. }
  102. //設置奇偶校驗位
  103. switch(parity)
  104. {
  105. case 'o':
  106. case 'O':
  107. {
  108. new_cfg.c_cflag|=(PARODD|PARENB);
  109. new_cfg.c_iflag|=(INPCK |ISTRIP);
  110. break;
  111. }
  112. case 'e':
  113. case 'E':
  114. {
  115. new_cfg.c_cflag |=PARENB;
  116. new_cfg.c_cflag &=~PARODD;
  117. new_cfg.c_iflag |=(INPCK | ISTRIP);
  118. break;
  119. }
  120. case 's':
  121. case 'S':
  122. {
  123. new_cfg.c_cflag &=~PARENB;
  124. new_cfg.c_cflag &=~CSTOPB;
  125. break;
  126. }
  127. case 'n':
  128. case 'N':
  129. {
  130. new_cfg.c_cflag &=~PARENB;
  131. new_cfg.c_iflag &=~INPCK;
  132. break;
  133. }
  134. }
  135. new_cfg.c_cc[VTIME] =10;
  136. new_cfg.c_cc[VMIN] =5;
  137. //處理未接收字符
  138. tcflush(fd,TCIFLUSH);
  139. if((tcsetattr(fd,TCSANOW,&new_cfg))!=0)
  140. {
  141. perror("tcsetattr");
  142. return -1;
  143. }
  144. return 0;
  145. }
  146. //打開串口函數
  147. int open_port(int com_port)
  148. {
  149. int fd;
  150. #if (COM_TYPE == GNR_COM) //使用普通串口
  151. char* dev[] = {"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};
  152. #else//使用USB轉串口
  153. char* dev[] = {"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2"};
  154. #endif
  155. if((com_port<0)||(com_port > MAX_COM_NUM))
  156. {
  157. return -1;
  158. }
  159. //打開串口
  160. if((fd=open(dev[com_port-1],O_RDWR|O_NOCTTY|O_NDELAY))<0)
  161. {
  162. perror("open serial port");
  163. return -1;
  164. }
  165. //恢復串口為堵塞狀態
  166. if(fcntl(fd,F_SETFL,0) <0 )
  167. {
  168. perror("fcntl F_SETFL\n");
  169. return -1;
  170. }
  171. //測試是否為終端設備
  172. if(isatty(STDIN_FILENO)==0)
  173. {
  174. perror("standard input is not a terminal device");
  175. }
  176. return fd;
  177. }
  178. void print_info(void)
  179. {
  180. //打印選擇界面,即引導的字符號
  181. printf("Now the receive time is %s\n",GPS_DATA.GPS_time);
  182. printf("The star is %c 3\n",GPS_DATA.GPS_sv);
  183. printf("The earth latitude is :%s\n",GPS_DATA.GPS_wd);
  184. printf("The earth longitude is :%s\n",GPS_DATA.GPS_jd);
  185. printf("The train speed is:%s km/h\n",GPS_DATA.GPS_speed);
  186. printf("The date is:%s\n",GPS_DATA.GPS_date);
  187. }
  188. void GPS_resolve_GPRMC(char data)
  189. {
  190. //$GPRMC,092427.604,V,4002.1531,N,11618.3097,E,0.000,0.00,280812,,E,N*08
  191. if(data==',')
  192. {
  193. ++SectionID;
  194. i=0;
  195. }
  196. else
  197. {
  198. switch(SectionID)
  199. {
  200. case 1://02:48:13
  201. GPS_DATA.GPS_time[i++]=data;
  202. if(i==2 || i==5)
  203. {
  204. GPS_DATA.GPS_time[i++]=':';
  205. }
  206. GPS_DATA.GPS_time[8]='\0';
  207. break;
  208. case 2:
  209. if(data=='A')
  210. GPS_DATA.GPS_sv='>';
  211. else
  212. GPS_DATA.GPS_sv='<';
  213. break;
  214. case 3://3158.4608
  215. GPS_DATA.GPS_wd[++i]=data;
  216. GPS_DATA.GPS_wd[12]='\0';
  217. break;
  218. case 4:
  219. if(data=='N')
  220. GPS_DATA.GPS_wd[0]='N';
  221. else if(data=='S')
  222. GPS_DATA.GPS_wd[0]='S';
  223. break;
  224. case 5://11848.3737,E
  225. GPS_DATA.GPS_jd[++i]=data;
  226. GPS_DATA.GPS_jd[12]='\0';
  227. break;
  228. case 6:
  229. if(data=='E')
  230. GPS_DATA.GPS_jd[0]='E';
  231. else if(data=='W')
  232. GPS_DATA.GPS_jd[0]='W';
  233. break;
  234. case 7://10.05
  235. GPS_DATA.GPS_speed[i++]=data;
  236. GPS_DATA.GPS_speed[4]='\0';
  237. break;
  238. case 9://15-07-06 -> 06-07-15
  239. GPS_DATA.GPS_date[i++]=data;
  240. if(i==2 || i==5)
  241. {
  242. GPS_DATA.GPS_date[i++]='-';
  243. }
  244. GPS_DATA.GPS_date[8]='\0';
  245. break;
  246. }
  247. }
  248. }
  249. void read_data(int fd)
  250. {
  251. char buffer[BUFF_SIZE],dest[1024];
  252. char array[10]="$GPRMC";
  253. int res,i=0,j=0,k;
  254. int data=1,len=0;
  255. memset(dest,0,sizeof(dest));
  256. do
  257. {
  258. memset(buffer,0,sizeof(buffer));
  259. //$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
  260. if(res=read(fd,buffer,1)>0)
  261. {
  262. //此處源源不斷傳入參數,一次讀到數據可能為($GPRMC,024),res為讀到長度,現在把每一位傳入函數處理;
  263. strcat(dest,buffer);
  264. if(buffer[0]=='\n')
  265. {
  266. i=0;
  267. if(strncmp(dest,array,6)==0)
  268. {
  269. printf("%s",dest);
  270. len=strlen(dest);
  271. for(k=0;k<len;k++)
  272. {
  273. GPS_resolve_GPRMC(dest[k]);
  274. }
  275. SectionID=0;
  276. print_info();
  277. }
  278. bzero(dest,sizeof(dest));
  279. }
  280. }
  281. }while(1);
  282. close(fd);
  283. }
  284. int main(int argc,char*argv[])
  285. {
  286. int fd=0;
  287. int HOST_COM_PORT=1;
  288. fd=open_port(HOST_COM_PORT);
  289. if(fd<0)
  290. {
  291. perror("open fail!");
  292. }
  293. printf("open sucess!\n");
  294. if((set_com_config(fd,9600,8,'N',1))<0)
  295. {
  296. perror("set_com_config fail!\n");
  297. }
  298. printf("The received worlds are:\n");
  299. read_data(fd);
  300. return 0;
  301. }
Copyright © Linux教程網 All Rights Reserved