惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
爱范儿
爱范儿
小众软件
小众软件
K
Kaspersky official blog
P
Proofpoint News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
V
Vulnerabilities – Threatpost
博客园_首页
Microsoft Security Blog
Microsoft Security Blog
C
Cybersecurity and Infrastructure Security Agency CISA
V
V2EX
C
Check Point Blog
S
Schneier on Security
P
Palo Alto Networks Blog
IT之家
IT之家
GbyAI
GbyAI
T
Threat Research - Cisco Blogs
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tailwind CSS Blog
Project Zero
Project Zero
Y
Y Combinator Blog
V
Visual Studio Blog
Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
S
Securelist
C
CERT Recently Published Vulnerability Notes
A
Arctic Wolf
M
MIT News - Artificial intelligence
人人都是产品经理
人人都是产品经理

博客园 - DoubleLi

Git 自动添加 git 子模块(.gitmodules) 如何在gitlab中使用子模块 CMake应用:模块化及库依赖 聊聊git push到远程服务器出现RPC failed问题 Qt Create多核编译配置 C++程序的发布部署方式及缺失依赖库dll的解决方法 VS+QT生成的exe文件所依赖的dll文件和路径 vs如何发布exe并附带动态链接库dll 详解 Visual Studio、MSVC、编译器版本,看完就不再困惑啦! MobaXterm使sftp目录与terminal目录同步 Loguru:Python 日志终极解决方案 VsCode C++ namespace has no member错误 VS Code 提示 namespace “std“ has no member “***“ 解决方法 windows平台中使用vscode远程连接linux进行c++开发配置教程(内容详细适合小白)-2021-3-30 vscode C++ 自动补全失效 从零开始的vscode安装及环境配置教程(C/C++)(Windows系统) VScode 完全卸载并清除原有配置 vscode中 “std“ 没有成员 “round“C/C++(135) vscode 提示 namespace “std“ has no member “mutex“ 的解决方法
从GPS/北斗模块中获取经纬度
DoubleLi · 2024-08-20 · via 博客园 - DoubleLi

一、前言

  GPS/北斗模块基本上都是通过串口发送数据的,并且发送数据的频率是1Hz,发送的数据内容可以去搜索“GPS数据格式”,反正这个模块发回来的数据很多,其中经纬度数据是包含在这些数据里面的。并且模块发回来的全部都是字符串,因此从GPS/北斗模块获取经纬度,实际上就是一个字符串解析的过程。

  比如:$GNRMC,143147.000,A,3413.64266,N,10851.97266,E,000.8,296.4,170821,,,A*7C

  这一帧数据里面就包含了经纬度,但数据格式是ddmm.mmmmm格式,比如这帧数据里面,“3413.64266”这个数是34度加13.64266分,分到度是60进制,因此要把分转换成度需要把分除以60,意思是13.64266分等于13.64266 / 60 = 0.227378度,那么3413.64266这个数就是34.227378度。同理经度也是一样。

  另外程序里还有一个坑,由于使用了atoi函数,使用这个函数需要包含stdlib.h,神奇的是在不包含stdlib.h的情况下编译程序也能通过,并且运行时也不会报错,但是atoi函数返回的结果是不对的。

二、代码

  程序代码很简单,编译时需要将uart.c也加入编译,并且要加-lm参数。uart.c参见我的另一篇博客:linux串口编程

复制代码

  1 /**
  2  * filename: gps.c
  3  * author: Suzkfly
  4  * date: 2021-08-21
  5  * platform: S3C2416
  6  * 编译时要加-lm
  7  */
  8  
  9 #include <stdio.h>
 10 #include <string.h>
 11 #include <math.h>
 12 #include <stdlib.h> /* 必须要包含stdlib.h,不然编译能通过,运行也不会报错,但atof函数运行的结果是错误的 */
 13 #include "uart.h"
 14 
 15 /**
 16  * \brief 从GPS/北斗模块中得到经纬度
 17  *
 18  * \param[in] fd:打开的串口设备的文件描述符
 19  * \param[out] p_lon:得到的经度
 20  * \param[out] p_lat:得到的纬度
 21  *
 22  * \retval 成功返回0,失败返回-1
 23  */
 24 int get_gps (int fd, char *p_lon, char *p_lat)
 25 {
 26     char buf[256] = { 0 };
 27     int  ret = 0;
 28     FILE *p_file = NULL;
 29     char *p_tmp = NULL;
 30     char lon_tmp[32] = { 0 };
 31     char lat_tmp[32] = { 0 };
 32     double d_lon = 0;
 33     double d_lat = 0;
 34     double d_tmp1 = 0;
 35     double d_tmp2 = 0;
 36     
 37     if ((p_lon == NULL) || (p_lat == NULL)) {
 38         return -1;
 39     }
 40     
 41     /* 文件描述符转文件流指针,为了方便获取一行数据 */
 42     p_file = fdopen(fd, "r");
 43     
 44     while (1) {
 45         p_tmp = fgets(buf, sizeof(buf), p_file);    /* 获取一行数据 */
 46         if (p_tmp == NULL) {
 47             continue;
 48         }
 49         
 50         if (strstr(buf, "$GNGGA") || strstr(buf, "$GPGGA")) {
 51             strtok(buf, ",");
 52             strtok(NULL, ",");
 53             p_tmp = strtok(NULL, ",");  
 54             strcpy(lat_tmp, p_tmp);   /* 第3次strtok得到纬度(度分格式) */
 55             
 56             strtok(NULL, ",");
 57             p_tmp = strtok(NULL, ",");
 58             strcpy(lon_tmp, p_tmp);   /* 第5次strtok得到经度(度分格式) */
 59             break;
 60         } else if (strstr(buf, "$GNRMC") || strstr(buf, "$GPRMC")) {
 61             strtok(buf, ",");
 62             strtok(NULL, ",");
 63             strtok(NULL, ",");
 64             p_tmp = strtok(NULL, ",");  
 65             strcpy(lat_tmp, p_tmp);   /* 第4次strtok得到纬度(度分格式) */
 66             
 67             strtok(NULL, ",");
 68             p_tmp = strtok(NULL, ",");
 69             strcpy(lon_tmp, p_tmp);   /* 第6次strtok得到经度(度分格式) */
 70             break;
 71         }
 72     }
 73     
 74     /* 将度分格式转换为度格式 */
 75     d_lon = atof(lon_tmp);
 76     d_lat = atof(lat_tmp);
 77     d_lon /= 100;
 78     d_lat /= 100;
 79     
 80     d_tmp1 = floor(d_lon);
 81     d_tmp2 = d_lon - d_tmp1;
 82     d_tmp2 *= 100;
 83     d_tmp2 /= 60;
 84     d_lon = d_tmp1 + d_tmp2;
 85     
 86     d_tmp1 = floor(d_lat);
 87     d_tmp2 = d_lat - d_tmp1;
 88     d_tmp2 *= 100;
 89     d_tmp2 /= 60;
 90     d_lat = d_tmp1 + d_tmp2;
 91         
 92     sprintf(p_lon, "%f", d_lon);
 93     sprintf(p_lat, "%f", d_lat);
 94     
 95     return 0;
 96 }
 97 
 98 /**
 99  * \brief example
100  */
101 int main(int argc, const char *argv[])
102 {
103     int fd = 0;
104     int ret = 0;
105     int pid = 0;
106     char buf[128] = { 0 };
107     int len = 0;
108     int i = 0;
109     char lon[32] = { 0 };
110     char lat[32] = { 0 };
111     
112     /* 打开串口设备 */
113     fd = uart_open(UART_DEV_PATH);
114     if (fd < 0) {
115         printf("open %s failed\n", UART_DEV_PATH);
116         return -1;
117     }
118 
119     /**
120      * 配置串口:
121      * 波特率:BAUD_RATE
122      * 数据位:8
123      * 校验  :无校验
124      * 停止位:1
125      * 流控  :无流控
126      */
127     ret = uart_set(fd, BAUD_RATE, 8, 'n', 1, 'n');
128     if (ret == -1) {
129         perror("uart set failed\n");
130         return -1;
131     }
132     
133     /* 得到GPS/北斗模块的经纬度 */
134     ret = get_gps(fd, lon, lat);
135     if (ret != 0) {
136         perror("get_gps error\n");
137         return -1;
138     }
139     
140     printf("Original Longitude = %s\n", lon);
141     printf("Original Latitude = %s\n", lat);
142     
143     return 0;
144 }

复制代码