第8章 USB

编程入门 行业动态 更新时间:2024-10-10 08:22:31

第8章 <a href=https://www.elefans.com/category/jswz/34/1762224.html style=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, &amp;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 &amp;= ~(ONLCR | OCRNL);
new_cfg.c_iflag &amp;= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
new_cfg.c_iflag &amp;= ~(ICRNL | INLCR);
new_cfg.c_iflag &amp;= ~(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(&amp;new_cfg, speed);<span class="hljs-comment">//输入波特率    </span>
cfsetospeed(&amp;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 &amp;= ~PARENB; new_cfg.c_iflag &amp;= ~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 &amp;= ~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 &amp;= ~PARENB;new_cfg.c_cflag &amp;= ~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 &amp;= ~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 &amp;= ~OPOST;  
new_cfg.c_lflag &amp;= ~(ICANON | ECHO | ECHOE | ISIG);<span class="hljs-comment">//我加的  </span>
new_cfg.c_lflag &amp;= ~(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, &amp;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 &lt; <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>)&lt;<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)) &lt; <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>) &lt; <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;
    #endif

    while(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>, &amp;gpgga.time, &amp;gpgga.lat, &amp;gpgga.lon,&amp;gpgga.state, &amp;gpgga.num, &amp;gpgga.hdop, &amp;gpgga.alt, &amp;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 &lt; <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 &lt; <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

本文发布于:2024-03-05 15:56:41,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1712733.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:USB

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!