USB"/>
第8章 USB
AT+QGPSLOC=2
+QGPSLOC: 053902.0,31.48653,120.31450,1.0,15.0,2,0.00,0.0,0.0,290421,08
/
查看参考手册,移远带有GPS的芯片的USB Serial如下。
2.1应用简介
1、若不使用 AT+QGPSCFG 指令对AG35进行配置,则会以默认参数开启GPS参数,NMEA端口开始上报,”gpsnmeatype”默认值为31,上报间隔为1s,每次上报所有种类的NMEA数据(GGA\RMC\GSV\GSA\VTG),若采用此默认配置,大多数使用者会觉得单次上报的数据太多且很多信息重复,建议大家使用QGPSCFG配置自己需要的NMEA数据格式,具体格式的差异可参考网上对NMEA数据的说明。
2、Linux环境下对NMEA数据的获取:
cat /dev/ttyUSB1 & // NMEA数据从ttyUSB1输出
echo “AT+QGPS=1” > /dev/ttyUSB2 // 开启GPS会话
可观察到ttyUSB1输出NMEA数据,如下:
3、程序设计过程中,若有固定频率更新位置需求,可考虑采用读取NMEA端口数据的形式,并将其配置适合自己需求的NMEA格式和数据更新间隔。若产品执行获取位置指令的频率较低且间隔时间不固定,也可考虑直接在AT指令端口使用AT+QGPSLOC指令进行实时位置信息的获取。
2.2 GPS数据解析
NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association )为海用电子设备制定的标准格式。目前业已成了GPS导航设备统一的RTCM(Radio Technical Commission for Maritime services)标准协议。
GPS接收机上电后,会自动通过串口或USB口发送NMEA0183格式的数据包,它是一组包含有各种地理位置信息的字符串,字符串格式为:
$信息类型,xxx,xxx,xxx,xxx,xxx,xxx,xxx,
每行开头的字符都是‘$’,接着是信息类型,后面是数据,以逗号分隔开。一行完整的数据如下:
$GPRMC,063102.00,A,2932.293196,N,10636.147385,E,0.0,45.5,250818,2.3,W,A*10
信息类型为:
GPVTG:地面速度信息
GPRMC:推荐最小定位信息
GPGSA:当前卫星信息
GPGGA:GPS定位信息
GPGSV:可见卫星信息
这里我们只解析GPRMC和GPGGA的信息。
GPRMC数据详解:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
< 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=数据无效)
解析内容:
1.时间,这个是格林威治时间,是世界时间(UTC),我们需要把它转换成北京时间(BTC),BTC和UTC差了8个小时,要在这个时间基础上加8个小时。
2.定位状态,在接收到有效数据前,这个位是‘V’,后面的数据都为空,接到有效数据后,这个位是‘A’,后面才开始有数据。
3.纬度,我们需要把它转换成度分秒的格式,计算方法:
如接收到的纬度是:4546.40891
4546.40891 / 100 = 45.4640891 可以直接读出45度
4546.40891–45 * 100 = 46.40891 可以直接读出46分
46.40891–46 = 0.40891 * 60 = 24.5346 读出24秒
所以纬度是:45度46分24秒。
4.南北纬,这个位有两种值‘N’(北纬)和‘S’(南纬)
5.经度的计算方法和纬度的计算方法一样
6.东西经,这个位有两种值‘E’(东经)和‘W’(西经)
7.速率,这个速率值是 海里/时,单位是节,要把它转换成千米/时,根据:1海里 = 1.85公里,把得到的速率乘以1.85。
8.航向,指的是偏离正北的角度
9.日期,这个日期是准确的,如:200818表示2018年08月20日,这个日期是准确的,不需要转换。
GPGGA数据详解
$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*xx
$GPGGA:起始引导符及语句格式说明(本句为GPS定位数据);
<1> UTC时间,格式为hhmmss.sss;
<2> 纬度,格式为ddmm.mmmm(第一位是零也将传送);
<3> 纬度半球,N或S(北纬或南纬)
<4> 经度,格式为dddmm.mmmm(第一位零也将传送);
<5> 经度半球,E或W(东经或西经)
<6> 定位质量指示,0=定位无效,1=定位有效;
<7> 使用卫星数量,从00到12(第一个零也将传送)
<8> 水平精确度,0.5到99.9
<9> 天线离海平面的高度,-9999.9到9999.9米 M 指单位米
<10> 大地水准面高度,-9999.9到9999.9米 M 指单位米
<11> 差分GPS数据期限(RTCM SC-104),最后设立RTCM传送的秒数量
<12> 差分参考基站标号,从0000到1023(首位0也将传送)。
2.3 GPS编程
GPS解析主要有两个部分,一个是USB转串口的配置,另外一个就是GPS的解析。下面就一一介绍。
1.串口配置
由于我是通过串口来进行数据传输,也就是把GPS定位的信息,通过串口最后输出到我们的终端设备上。
【uart_GPS_config.c】
/********************************************************************************* @file uart_GPS_config.c* @author Bruceou* @version V1.0* @date 2018.04.11* @brief 串口设置*******************************************************************************/
/**Includes*********************************************************************/
#include "uart_GPS_config.h"
/**
* @brief 串口设置函数
* @param fd
baud_rate
data_bits
parity
stop_bits
* @retval int
*/
int set_GPS_com_config(int fd,int baud_rate,int data_bits, char parity, int stop_bits)
{
struct termios new_cfg;
int speed;
<span class="hljs-comment">/* 保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息 */</span><span class="hljs-keyword">if</span> (tcgetattr(fd, &new_cfg) != <span class="hljs-number">0</span>)
{perror(<span class="hljs-string">"tcgetattr save"</span>); <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
}<span class="hljs-comment">//修改控制模式,保证程序不会占用串口 </span>
new_cfg.c_cflag |= CLOCAL;
<span class="hljs-comment">//修改控制模式,使得能够从串口中读取输入数据 </span>
new_cfg.c_cflag |= CREAD;
new_cfg.c_oflag &= ~(ONLCR | OCRNL);
new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
new_cfg.c_iflag &= ~(ICRNL | INLCR);
new_cfg.c_iflag &= ~(IXON | IXOFF | IXANY);<span class="hljs-comment">/* 设置波特率 */</span>
<span class="hljs-keyword">switch</span> (baud_rate)
{<span class="hljs-keyword">case</span> <span class="hljs-number">2400</span>: {speed = B2400; }<span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> <span class="hljs-number">4800</span>:{speed = B4800;}<span class="hljs-keyword">break</span>;<span class="hljs-keyword">case</span> <span class="hljs-number">9600</span>:{speed = B9600;}<span class="hljs-keyword">break</span>;<span class="hljs-keyword">case</span> <span class="hljs-number">19200</span>:{speed = B19200;}<span class="hljs-keyword">break</span>;<span class="hljs-keyword">case</span> <span class="hljs-number">38400</span>: {speed = B38400;}<span class="hljs-keyword">break</span>;<span class="hljs-keyword">default</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">115200</span>: {speed = B115200; } <span class="hljs-keyword">break</span>;
}cfsetispeed(&new_cfg, speed);<span class="hljs-comment">//输入波特率 </span>
cfsetospeed(&new_cfg, speed);<span class="hljs-comment">//输出波特率</span>
<span class="hljs-keyword">switch</span> (data_bits) <span class="hljs-comment">/* 设置数据位 */</span>
{ <span class="hljs-keyword">case</span> <span class="hljs-number">7</span>:{new_cfg.c_cflag |= CS7; } <span class="hljs-keyword">break</span>; <span class="hljs-keyword">default</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">8</span>:{new_cfg.c_cflag |= CS8;} <span class="hljs-keyword">break</span>;
}<span class="hljs-keyword">switch</span> (parity) <span class="hljs-comment">/* 设置奇偶校验位 */</span>
{<span class="hljs-keyword">default</span>: <span class="hljs-keyword">case</span> <span class="hljs-string">'n'</span>: <span class="hljs-keyword">case</span> <span class="hljs-string">'N'</span>: {new_cfg.c_cflag &= ~PARENB; new_cfg.c_iflag &= ~INPCK; } <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> <span class="hljs-string">'o'</span>:<span class="hljs-keyword">case</span> <span class="hljs-string">'O'</span>:{new_cfg.c_cflag |= (PARODD | PARENB); new_cfg.c_iflag |= INPCK; } <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> <span class="hljs-string">'e'</span>:<span class="hljs-keyword">case</span> <span class="hljs-string">'E'</span>:{new_cfg.c_cflag |= PARENB; new_cfg.c_cflag &= ~PARODD; new_cfg.c_iflag |= INPCK; } <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> <span class="hljs-string">'s'</span>: <span class="hljs-comment">/* as no parity */</span> <span class="hljs-keyword">case</span> <span class="hljs-string">'S'</span>:{new_cfg.c_cflag &= ~PARENB;new_cfg.c_cflag &= ~CSTOPB;} <span class="hljs-keyword">break</span>;
}
<span class="hljs-keyword">switch</span> (stop_bits) <span class="hljs-comment">/* 设置停止位 */</span>
{<span class="hljs-keyword">default</span>:<span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:{new_cfg.c_cflag &= ~CSTOPB; } <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:{new_cfg.c_cflag |= CSTOPB; }
}
<span class="hljs-comment">//修改输出模式,原始数据输出 </span>
new_cfg.c_oflag &= ~OPOST;
new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);<span class="hljs-comment">//我加的 </span>
new_cfg.c_lflag &= ~(ISIG | ICANON); <span class="hljs-comment">//设置等待时间和最小接收字符 </span>
new_cfg.c_cc[VTIME] = <span class="hljs-number">0</span>; <span class="hljs-comment">/* 读取一个字符等待0*(0/10)s */</span>
new_cfg.c_cc[VMIN] = <span class="hljs-number">1</span>; <span class="hljs-comment">/* 读取字符的最少个数为0 */</span> <span class="hljs-comment">//如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读</span>
tcflush(fd, TCIFLUSH); <span class="hljs-comment">/* 处理未接收字符 */</span>
<span class="hljs-keyword">if</span> ((tcsetattr(fd, TCSANOW, &new_cfg)) != <span class="hljs-number">0</span>) <span class="hljs-comment">/* **新配置 */</span>
{perror(<span class="hljs-string">"tcsetattr action"</span>);<span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
}
<span class="hljs-comment">//printf("serial set success\n");</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
/**
* @brief 打开串口函数
* @param com
* @retval int
*/
int open_GPS_port(const char *com_port)
{
int fd;
<span class="hljs-comment">/*分别为com1,com2, com3对应 ttyS0 ttyS1 ttyS2 */</span>
fd = open( com_port, O_RDWR|O_NOCTTY|O_NDELAY);
<span class="hljs-keyword">if</span> (fd < <span class="hljs-number">0</span>)
{perror(<span class="hljs-string">"Can't Open Serial Port"</span>); <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
}
<span class="hljs-comment">/*恢复串口为阻塞状态*/</span>
<span class="hljs-keyword">if</span> (fcntl(fd,F_SETFL,<span class="hljs-number">0</span>)<<span class="hljs-number">0</span>)
{perror(<span class="hljs-string">"fcntl F_SETFL\n"</span>);
}
<span class="hljs-comment">/*测试是否为终端设备*/</span>
<span class="hljs-keyword">if</span>(isatty(STDIN_FILENO) == <span class="hljs-number">0</span>)
{perror(<span class="hljs-string">"standard input is not a terminal device"</span>);
}
<span class="hljs-keyword">return</span> fd;
}
/**
* @brief 串口初始化函数
* @param com_port
* @retval int
*/
int init_GPS_port(const char *com_port)
{
int fd;
<span class="hljs-keyword">if</span> ((fd = open_GPS_port(com_port)) < <span class="hljs-number">0</span> )
{perror(<span class="hljs-string">"open_port"</span>);<span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
}<span class="hljs-keyword">if</span>(set_GPS_com_config(fd,<span class="hljs-number">9600</span>,<span class="hljs-number">8</span>,<span class="hljs-string">'N'</span>,<span class="hljs-number">1</span>) < <span class="hljs-number">0</span>)
{perror(<span class="hljs-string">"set_com_config"</span>);<span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
}
<span class="hljs-keyword">return</span> fd;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
【uart_GPS_config.h】
#ifndef _UART_GPS_CONFIG_H_
#define _UART_GPS_CONFIG_H_
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <termios.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#define BUFFER_SIZE 36
#define DEVICE_AT_GPS “/dev/ttyUSB2”
#define DEVICE_DATA_GPS “/dev/ttyUSB1”
int set_GPS_com_config(int fd,int baud_rate, int data_bits,char parity,int stop_bits);
int open_GPS_port(const char *com_port);
int init_GPS_port(const char *com_port);
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
2.GPS数据分析
【GPS.c】
/********************************************************************************* @file GPS.c* @author Bruceou* @version V1.0* @date 2018.08.11* @brief GPS 解析*******************************************************************************/
/**Includes*********************************************************************/
#include "GPS.h"
char *buff = NULL;
GPRMC_t gprmc;
GPGGA_t gpgga;
/**
* @brief GPS解析函数
* @param AT_fd:串口文件描述符
-
@ DATA_fd:串口文件描述符
* @retval Nono
*/
void GPS_Analysis(int AT_fd,int DATA_fd)
{
int nread,nwrite;
char send_buff[16];
char recv_buff[512];
char *ptr = NULL;
char AT_Buff[16];
int ret = 0;
#if 0
uint32_t time =0;
uint32_t lat =0 ;
uint32_t lon =0;
uint32_t speed =0;
uint32_t head =0;
uint32_t alt =0;
#endifwhile(1)
{
memset(AT_Buff,0,sizeof(AT_Buff));
strcpy(AT_Buff, “AT+QGPS=1”);
GPS_Set(AT_fd , AT_Buff);<span class="hljs-keyword">if</span>(buff != NULL) {<span class="hljs-keyword">break</span>; }memset(AT_Buff,<span class="hljs-number">0</span>,sizeof(AT_Buff)); strcpy(AT_Buff, <span class="hljs-string">"AT+QGPSEND"</span>); GPS_Set(AT_fd , AT_Buff); sleep(<span class="hljs-number">1</span>);
}
//接收数据
while(1)
{
memset(&gprmc, 0, sizeof(gprmc));
memset(&gpgga, 0, sizeof(gpgga));
memset(recv_buff,0,sizeof(recv_buff));
nread = read(DATA_fd,recv_buff,sizeof(recv_buff));
#ifdef DEBUG_GPS
printf(“nread=%d,%s\n”,nread,recv_buff);
printf("=2===\n");
#endif
//strcpy(buff, recv_buff);
//保存数据
ptr = strstr(recv_buff, “ G P R M C " < / s p a n > ) ; r e t = s s c a n f ( p t r , < s p a n c l a s s = " h l j s − s t r i n g " > " GPRMC"</span>); ret = sscanf(ptr, <span class="hljs-string">" GPRMC"</span>);ret=sscanf(ptr,<spanclass="hljs−string">"GPRMC,%f,%c,%f,%*c,%f,%*c,%f,%f,%d,%f,%*c,%c”,
&gprmc.time,&gprmc.state, &gprmc.lat, &gprmc.lon,
&gprmc.speed, &gprmc.head, &gprmc.date,&gprmc.dec);
ptr = strstr(recv_buff, <span class="hljs-string">"$GPGGA"</span>);ret = sscanf(ptr, <span class="hljs-string">"$GPGGA,%f,%f,N,%f,E,%d,%d,%f,%f,M,%f,M,,*"</span>, &gpgga.time, &gpgga.lat, &gpgga.lon,&gpgga.state, &gpgga.num, &gpgga.hdop, &gpgga.alt, &gpgga.geoid);
#if 0
time = (int)(gprmc.time*100) % 100 + ((int)gprmc.time % 100) * 100 +
((int)gprmc.time%10000/100) 60 * 100 + ((int)gprmc.time/10000) 3600 * 100;
lat = ((<span class="hljs-keyword">int</span>)(gprmc.lat/<span class="hljs-number">100</span>) + (gprmc.lat-(<span class="hljs-keyword">int</span>)gprmc.lat/<span class="hljs-number">100</span>*<span class="hljs-number">100</span>)/<span class="hljs-number">60</span>)*<span class="hljs-number">10000000</span>;lon = ((<span class="hljs-keyword">int</span>)(gprmc.lon/<span class="hljs-number">100</span>) + (gprmc.lon-(<span class="hljs-keyword">int</span>)gprmc.lon/<span class="hljs-number">100</span>*<span class="hljs-number">100</span>)/<span class="hljs-number">60</span>)*<span class="hljs-number">10000000</span>;speed = gprmc.speed* <span class="hljs-number">1.852</span>;head = gprmc.head;alt = gpgga.alt;
#endif
//打印数据
print_GPS_RMC(&gprmc);
print_GPS_GGA(&gpgga);
}
}
/**
* @brief GPS打开函数
* @param AT_fd:串口文件描述符
-
@ AT :AT指令
* @retval Nono
*/
void GPS_Set(int AT_fd,char *AT)
{
int nread,nwrite;
char send_buff[16];
char recv_buff[64];memset(send_buff,0,sizeof(send_buff));
strcpy(send_buff, AT);
strcat(send_buff,"\r");
nwrite = write(AT_fd,send_buff,strlen(send_buff));
#ifdef DEBUG_GPS
printf(“nwrite=%d,%s\n”,nwrite,send_buff);
#endif
//waiting for AT’s ACK等待回应
memset(recv_buff,0,sizeof(recv_buff));
nread = read(AT_fd,recv_buff,sizeof(recv_buff));
buff = strstr(recv_buff,<span class="hljs-string">"OK"</span>);
<span class="hljs-comment">//memset(buff,0,strlen(buff));</span>
#ifdef DEBUG_GPS
printf(“nread=%d,%s\n”,nread,recv_buff);
printf(“1======\n”);
#endif
}
/**
* @brief GPS-RMC信息打印
* @param gprmc_data:
* @retval Nono
*/
void print_GPS_RMC(GPRMC_t *gprmc_data)
{
printf(" \n");
printf("=\n");
printf(" 全球GPS定位导航模块 \n");
printf(" Author:BruceOu \n");
printf(" Email:bruceoxl@qq \n");
printf("RMC信息\n");
printf("=\n");
printf(" GPS state bit : %c [A:有效状态 V:无效状态] \n",gprmc_data->state);
printf(" Date : 20%02d-%02d-%02d \n",gprmc_data->date%100,(gprmc_data->date%10000)/100,gprmc_data->date/10000);
printf(" 纬度 : 北纬:%d度%d分%d秒 \n",((int)gprmc_data->lat) / 100, (int)(gprmc_data->lat - ((int)gprmc_data->lat / 100 * 100)), (int)(((gprmc_data->lat - ((int)gprmc_data->lat / 100 * 100)) - ((int)gprmc_data->lat - ((int)gprmc_data->lat / 100 * 100))) * 60.0));
printf(" 经度 : 东经:%d度%d分%d秒 \n",((int)gprmc_data->lon) / 100, (int)(gprmc_data->lon - ((int)gprmc_data->lon / 100 * 100)), (int)(((gprmc_data->lon - ((int)gprmc_data->lon / 100 * 100)) - ((int)gprmc_data->lon - ((int)gprmc_data->lon / 100 * 100))) * 60.0));
printf(" 速度 : %.3f m/s \n",gprmc_data->speed * 1.852);
printf(" 航向 : %.3f 度 \n",gprmc_data->head );
printf("===================================================\n");
}
/**
* @brief GPS-GGA信息打印
* @param gpgga_data:
* @retval Nono
*/
void print_GPS_GGA(GPGGA_t *gpgga_data)
{
printf(" \n");
printf("=\n");
printf(" 全球GPS定位导航模块 \n");
printf(" Author:BruceOu \n");
printf(" Email:bruceoxl@qq \n");
printf("GGA信息\n");
printf("=\n");
printf(" 纬度 : 北纬:%d度%d分%d秒 \n",((int)gpgga_data->lat) / 100, (int)(gpgga_data->lat - ((int)gpgga_data->lat / 100 * 100)), (int)(((gpgga_data->lat - ((int)gpgga_data->lat / 100 * 100)) - ((int)gpgga_data->lat - ((int)gpgga_data->lat / 100 * 100))) * 60.0));
printf(" 经度 : 东经:%d度%d分%d秒 \n",((int)gpgga_data->lon) / 100, (int)(gpgga_data->lon - ((int)gpgga_data->lon / 100 * 100)), (int)(((gpgga_data->lon - ((int)gpgga_data->lon / 100 * 100)) - ((int)gpgga_data->lon - ((int)gpgga_data->lon / 100 * 100))) * 60.0));
printf(" 数量 : %d 颗 \n",gpgga_data->num);
printf(" 精度 : %.3f \n",gpgga_data->hdop);
printf(" 海拔 : %.3f m \n",gpgga_data->alt);
printf("=================================================\n");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
【GPS.h】
#ifndef _GPS_H_
#define _GPS_H_
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <assert.h>
#include <iconv.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include “uart_GPS_config.h”
#define DEBUG_GPS
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef struct _GPRMC
{
float time;//UTC时间,hhmmss(时分秒)格式/* gps定位时间 */
uint8_t state;/gps状态位//A=有效定位,V=无效定位/
float lat;/*纬度 /
float lon;/ 经度 */
float speed;/*速度 */
float head;/*航向 /
uint32_t date;/日期/
float dec;/ 磁偏角 */
uint8_t dd;/磁偏角方向/
uint8_t mode;/GPS模式位//A=自主定位,D=差分,E=估算,N=数据无效/
}GPRMC_t;
typedef struct _GPGGA
{
float time;//UTC时间,hhmmss(时分秒)格式/* gps定位时间 */
float lat;/*纬度 /
float lon;/ 经度 */
uint32_t state;/gps状态位//0=定位无效,1=定位有效;/
uint32_t num;/使用卫星数量,从00到12(第一个零也将传送)/
float hdop;/水平精确度,0.5到99.9/
float alt;/天线离海平面的高度,-9999.9到9999.9米/
float geoid;
}GPGGA_t;
void GPS_Analysis(int AT_fd,int DATA_fd);
void GPS_Set(int AT_fd,char *AT);
void print_GPS_RMC(GPRMC_t *gprmc_data);
void print_GPS_GGA(GPGGA_t *gpgga_data);
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
【注意】
1.由于我直接获取的是格林威治时间即世界时间(UTC),所以要把它转换成北京时间(BTC),也就是在这个时间基础上加8个小时。
2.经纬度,GPRMC返回的纬度数据位ddmm.mmmm格式即度分格式,我们把它转换成常见的度分秒的格式,计算方法:如接收到的纬度是:3029.60430
3029.60430/100=
30.2960430可以直接读出30度, 3029.60430–30*100=29.60430, 可以直接读出29分 (29.60430–29)*60 =0.60430*60=36.258读出36秒, 所以纬度是:30度29分36秒。
3.GPRMC返回的速率值是海里/时,单位是节,把它转换成千米/时,换算为:1海里=1.85公里,把得到的速率乘以1.85。
4.航向指的是偏离正北的角度。
5.GPRMC的日期格式为:ddmmyy,如:200818表示2018年08月20日,这个日期是准确的,不需要转换。
3.主函数打开串口设备读操作
【main.c】
/********************************************************************************* @file main.c* @author Bruceou* @version V1.0* @date 2018.08.11* @brief *******************************************************************************/
/**Includes*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "uart_GPS_config.h"
#include "GPS.h"
#define DEBUG_GPS
int GPS_DATA_fd = -1; //GPS_DATA描述符
int GPS_AT_fd = -1; //GPS_AT描述符;
/**
* @brief main函数
* @param Nono
* @retval Nono
*/
int main(int argc, char **argv)
{
GPS_AT_fd = init_GPS_port(DEVICE_AT_GPS); //初始化AT GPS
<span class="hljs-keyword">if</span>(GPS_AT_fd < <span class="hljs-number">0</span>)
{printf(<span class="hljs-string">"open GPS_AT_port failed!\n"</span>);
}
<span class="hljs-keyword">else</span>
{printf(<span class="hljs-string">"open GPS_AT_port success!\n"</span>);
}GPS_DATA_fd = init_GPS_port(DEVICE_DATA_GPS); <span class="hljs-comment">//初始化DATA GPS</span><span class="hljs-keyword">if</span>(GPS_AT_fd < <span class="hljs-number">0</span>)
{printf(<span class="hljs-string">"open GPS_DATA_port failed!\n"</span>);
}
<span class="hljs-keyword">else</span>
{printf(<span class="hljs-string">"init GPS_port success!\n"</span>);GPS_Analysis(GPS_AT_fd,GPS_DATA_fd);
}<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
【注】AG35的USB转串口信息在本文前已经给出,需要使用两个设备,ttyUSB1和ttyUSB2,ttyUSB1是GPS输出信息,ttyUSB2是AT命令配置设备,因此需要打开两个设备。
【Makefile】
APPS := gps_app
CC := arm-fsl-linux-gnueabi-gcc#交叉编译工具
srcs := *.c
all: ( < / s p a n > s r c s ) < s p a n c l a s s = " h l j s − v a r i a b l e " > (</span>srcs) <span class="hljs-variable"> (</span>srcs)<spanclass="hljs−variable">(CC) ( < / s p a n > s r c s ) − o < s p a n c l a s s = " h l j s − v a r i a b l e " > (</span>srcs) -o <span class="hljs-variable"> (</span>srcs)−o<spanclass="hljs−variable">(APPS)
clean:
rm $(APPS)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
4.测试
编译完成后,执行程序,会有下面的主要信息,可以看到GPS的解析数据。
参考:
Quectel_EC20_GNSS_AT_Commands_Manual_V1.1.pdf
NMEA码详解:.html
更多推荐
第8章 USB
发布评论