STM32使用HAL库获取GPS模块HT1818Z3G5L信息(方法1)

1、写在最前

先了解一下GPRMC的格式
格 式:
GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,A*50
说 明:
字段 0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
字段 1:UTC时间,hhmmss.sss格式
字段 2:状态,A=定位,V=未定位
字段 3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
字段 4:纬度N(北纬)或S(南纬)
字段 5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
字段 6:经度E(东经)或W(西经)
字段 7:速度,节,Knots(一节也是1.852千米/小时)
字段 8:方位角,度(二维方向指向,相当于二维罗盘)
字段 9:UTC日期,DDMMYY格式
字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
字段11:磁偏角方向,E=东,W=西
字段12:模式,A=自动,D=差分,E=估测,N=数据无效(3.0协议内容)
字段13:校验值

2、配置

使用STM32F103C8T6的串口1,连接模块的串口。
此模块4个引脚标注为“V G T R”
在这里插入图片描述

功能:
V = 3.3V
G = GND
T = TX
R = RX

STM32CUBE配置如下:
在这里插入图片描述
在这里插入图片描述
记得开启串口中断。

3、程序编写

1、先使用单字节接收方式,因为每个帧的结构都是$开头,0x0d,0x0a结尾。如果使用空闲接收的话,这个模块一次发送的数据比较大,需要大几百字节的缓存。
首先在main函数中,先定义需要的全局变量

uint8_t g_ucRxByte;
uint8_t g_ucRxCnt;
uint8_t g_ucaRx[GPS_BUFF_SIZE];
rtcType_T g_tRtcCN;
float g_fSpeed;

在这里插入图片描述
2、进入主循环之前,开启串口接收

  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1,&g_ucRxByte,1);
  /* USER CODE END 2 */

3、编写GPS.h头文件

#ifndef __GPS_H
#define __GPS_H
#include "main.h"

#define GPS_BUFF_SIZE	100

typedef struct
{
	uint16_t usYear;
	uint8_t ucMonth;
	uint8_t ucDay;
	uint8_t ucHour;
	uint8_t ucMinute;
	uint8_t ucSecond;
}rtcType_T;

extern uint8_t g_ucaGNRMC[GPS_BUFF_SIZE];
extern uint8_t g_ucGNRMCRxSta;

uint8_t GPS_GetTime(char *cpRmc,rtcType_T *tpRTC);/*从RMC(推荐最小定位信息)中获取GPS的时间信息,东8区时间*/
rtcType_T GPS_TimeToArea(rtcType_T tTime, uint8_t ucArea);/*转换GPS时间到指定区的时间*/
float GPS_GetSpeed(char *cpRmc);

#endif

4、编写GPS.c文件

#include "gps.h"
#include "string.h"
#include "stdlib.h"

uint8_t g_ucaGNRMC[GPS_BUFF_SIZE];
uint8_t g_ucGNRMCRxSta;


uint8_t GPS_GetTime(char *cpRmc,rtcType_T *tpRTC)
{
	char *cpStart;
	uint8_t i;

	cpStart = strchr(cpRmc,',');
	
	tpRTC->ucHour = (cpStart[1]-0x30)*10 + (cpStart[2]-0x30) ;/**/

	tpRTC->ucMinute = (cpStart[3]-0x30)*10 + (cpStart[4]-0x30);
	tpRTC->ucSecond = (cpStart[5]-0x30)*10 + (cpStart[6]-0x30);
	
	cpStart = cpRmc;
	for(i = 0;i < 9;i++)
	{
		cpStart = strchr(cpStart,',');
		cpStart++;
	}
	tpRTC->ucDay = (cpStart[0]-0x30)*10 + (cpStart[1]-0x30);
	tpRTC->ucMonth = (cpStart[2]-0x30)*10 + (cpStart[3]-0x30);
	tpRTC->usYear = (cpStart[4]-0x30)*10 + (cpStart[5]-0x30) + 2000;
	
	return 1;

}


rtcType_T GPS_TimeToArea(rtcType_T tTime, uint8_t ucArea)
{
	rtcType_T tConvertTime;
	tConvertTime = tTime;
	tConvertTime.ucHour += ucArea;
	if(1==tConvertTime.ucMonth||3==tConvertTime.ucMonth||5==tConvertTime.ucMonth||7==tConvertTime.ucMonth||8==tConvertTime.ucMonth||10==tConvertTime.ucMonth||12==tConvertTime.ucMonth)//1,3,5,7,8,9,12月每月为31天
	{
		if(24 <= tConvertTime.ucHour)
		{
			tConvertTime.ucHour -= 24;
			tConvertTime.ucDay += 1;//如果超过24小时,减去24小时,后再加上一天
			if(tConvertTime.ucDay > 31)
			{
				tConvertTime.ucDay -= 31;
				tConvertTime.ucMonth += 1;
			}//如果超过31一天,减去31天,后加上一个月
		}
	}
	else if(4==tConvertTime.ucMonth||6==tConvertTime.ucMonth||9==tConvertTime.ucMonth||11==tConvertTime.ucMonth)//4,6,9,11月每月为30天
	{
		if(24 <= tConvertTime.ucHour)
		{
			tConvertTime.ucHour -= 24;
			tConvertTime.ucDay += 1;//如果超过24小时,减去24小时,后再加上一天
			if(30 < tConvertTime.ucDay)
			{
				tConvertTime.ucDay -= 30;
				tConvertTime.ucMonth += 1;
			}//如果超过30一天,减去30天,后加上一个月
		}
	}
	else//剩下为2月,闰年为29天,平年为28天
	{
		if(24 <= tConvertTime.ucHour)
		{
			tConvertTime.ucHour -= 24;
			tConvertTime.ucDay += 1;
			if((0 == tConvertTime.usYear%400)||(0 == tConvertTime.usYear%4 && 0 != tConvertTime.usYear%100))//判断是否为闰年,年号能被400整除或年号能被4整除,而不能被100整除为闰年
			{
				if(29 < tConvertTime.ucDay)
				{
					tConvertTime.ucDay -= 29;
					tConvertTime.ucMonth += 1;
				}
			}//为闰年
			else
			{
				if(28 < tConvertTime.ucDay)
				{
					tConvertTime.ucDay -= 28;
					tConvertTime.ucMonth += 1;
				}
			}//为平年
		}
 
	}
	if(12 < tConvertTime.ucMonth)
	{
		tConvertTime.ucMonth-=12;
		tConvertTime.usYear+=1;
	}
	return tConvertTime;
}

/*GNRMC的第7个字段为速度,节,Knots(一节也是1.852千米/小时)*/
float GPS_GetSpeed(char *cpRmc)
{
	float fSpeed;
	char *cpStart,*cpEnd,*ptr;
	uint8_t i,ucLenth;
	char caTmp[10];
	
	memset(caTmp,0,10);
	
	cpStart = cpRmc;
	for(i = 0;i < 7;i++)
	{
		cpStart = strchr(cpStart,',');
		cpStart++;
	}
	cpEnd = strchr(cpStart,',');
	ucLenth = cpEnd - cpStart;
	memcpy(caTmp,cpStart,ucLenth);
	caTmp[ucLenth] = '\0';
	fSpeed = strtof(caTmp,&ptr);
	fSpeed = fSpeed * 1.852;
	return fSpeed;
}

文件中使用了字符串转浮点数函数,如果不需要速度,可以取消,同时无需包含#include “stdlib.h”

5、返回主函数,进行中断回调函数的编写。

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(g_ucRxByte == '$')
	{
		g_ucRxCnt = 0;
	}
	else if(g_ucRxByte == 0x0a)/*一帧结束*/
	{
		if(g_ucaRx[0]=='$' && g_ucaRx[4]=='M' && g_ucaRx[5]=='C')/*只提取GNRMC*/
		{
			memcpy(g_ucaGNRMC,g_ucaRx,g_ucRxCnt);
			g_ucGNRMCRxSta = g_ucRxCnt | 0x80;
		}
	}
	
	g_ucaRx[g_ucRxCnt++] = g_ucRxByte;
	
	if(g_ucRxCnt >= GPS_BUFF_SIZE)	
	{
		g_ucRxCnt = 0;
	}
	
	HAL_UART_Receive_IT(&huart1,&g_ucRxByte,1);
}
/* USER CODE END 4 */

6、使用模块
在主循环中,解析获取的GNRMC数据。

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if(g_ucGNRMCRxSta & 0x80)
	  {
		  g_ucGNRMCRxSta = 0;
		  GPS_GetTime((char *)g_ucaGNRMC,&tRTCGps);
		  g_tRtcCN = GPS_TimeToArea(tRTCGps,8);
		  g_fSpeed = GPS_GetSpeed((char *)g_ucaGNRMC);
	  }
  }
  /* USER CODE END 3 */

在这里插入图片描述

7、结果
在这里插入图片描述

4、写在最后

这个模块一般般吧,我把模块放到靠近窗户,定位时有时无,定位成功后,静止状态的速度也会跳动。如果需要获取有效的速度信号,可能需要其他辅助,例如运动检测等判断是否在静止状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/520723.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Open CASCADE学习|在给定的TopoDS_Shape中查找与特定顶点 V 对应的TopoDS_Edge编号

enum TopAbs_ShapeEnum{TopAbs_COMPOUND,TopAbs_COMPSOLID,TopAbs_SOLID,TopAbs_SHELL,TopAbs_FACE,TopAbs_WIRE,TopAbs_EDGE,TopAbs_VERTEX,TopAbs_SHAPE}; 这段代码定义了一个名为 TopAbs_ShapeEnum 的枚举类型&#xff0c;它包含了表示不同几何形状类型的常量。这些常量通常…

通过学习mayfly-go,我学会了前端如何优雅设计字典值

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen shigen在假期的最后一天早晨起来&#xff0c;翻看了一下博客&#xff0c;一个ma…

spring注解驱动系列--声明式事务

一、环境搭建 一、导入依赖 <!-- 数据源、数据库驱动、spring-jdbc模块--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.12.RE…

Dockerfile详解构建镜像

Dockerfile构建企业级镜像 在服务器上可以通过源码或rpm方式部署Nginx服务&#xff0c;但不利于大规模的部署。为提高效率&#xff0c;可以通过Dockerfile的方式将Nginx服务封装到镜像中&#xff0c;然后Docker基于镜像快速启动容器&#xff0c;实现服务的快速部署。 Dockerf…

统一网关 Gateway(黑马程序员)

网关的技术实现 在 SpringCloud 中网关的实现包括两种&#xff1a; gatewayzuul Zuul 是基于 Servlet 的实现&#xff0c;属于阻塞式编程。而 SpringCloudGateway 则是基于 Spring5 中提供的 WebFlux &#xff0c; 属于响应式编程的实现&#xff0c;具备更好的性能。 网关的作…

火柴排队(c++实现)

题目 涵涵有两盒火柴&#xff0c;每盒装有 n 根火柴&#xff0c;每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列&#xff0c;同一列火柴的高度互不相同&#xff0c;两列火柴之间的距离定义为&#xff1a; 其中 ai 表示第一列火柴中第 i 个火柴的高度&#xf…

【OneAPI】贴纸生成API

OneAPI新接口发布&#xff1a;贴纸生成 生成一个10241024像素的贴纸。 API地址&#xff1a;POST https://oneapi.coderbox.cn/openapi/api/stickers 请求参数&#xff08;body&#xff09; 参数名类型必填含义说明prompt提示词是提示词示例&#xff1a;一只可爱的小狗 响应…

网络网络层之(1)IPv4地址

网络网络层之(1)IPv4地址 Author: Once Day Date: 2024年4月1日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的…

嵌入式系统初学者指南

什么是嵌入式系统&#xff1f; 嵌入式系统是一种独立的、基于微处理器的计算机系统。您可以将其视为大型系统的一部分的微型计算机。如今&#xff0c;从洗碗机到波音 747&#xff0c;几乎所有“电子”产品内部都有嵌入式系统。但是&#xff0c;嵌入式系统与笔记本电脑或手机不…

mysql dublewrite 双写缓存机制

mysql dublewrite 双写缓存机制&#xff0c;像不像主板双bois系统&#xff0c; 在MySQL的InnoDB存储引擎中&#xff0c;当进行数据写操作时&#xff0c;会先将数据写入到内存中的缓冲池&#xff08;Buffer Pool&#xff09;&#xff0c;然后异步刷新到磁盘上的数据文件。为了提…

基于巴法云物联网云平台构建可视化控制网页(以控制LED为例)

0 前言 如今大大小小的物联网云平台非常多&#xff0c;但大部分要收取费用&#xff0c;免费的物联网云平台功能则有很多限制使用起来非常不方便。以百度云物联网云平台为例&#xff0c;它的物可视不支持发布主题&#xff0c;等于可视化界面只能作为数据监控而不具备双向通信的…

打造个人高效图床系统:威联通NAS+兰空+PicGo全方位整合教程

1.图床选择 最近因为家里人有使用图床的需求&#xff0c;又担心第三方图床跑路导致数据丢失&#xff0c;恰好家里有个威联通NAS&#xff0c;还有公网IP和域名&#xff0c;既然如此&#xff0c;那就动手自建一个图床吧&#xff0c;毕竟开源的图床应用还是有很多的。 一上来就在…

掌握数据相关性新利器:基于R、Python的Copula变量相关性分析及AI大模型应用探索

在工程、水文和金融等各学科的研究中&#xff0c;总是会遇到很多变量&#xff0c;研究这些相互纠缠的变量间的相关关系是各学科的研究的重点。虽然皮尔逊相关、秩相关等相关系数提供了变量间相关关系的粗略结果&#xff0c;但这些系数都存在着无法克服的困难。例如&#xff0c;…

写JDBC遇到的问题

执行会出现以下错误信息 java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ? and loginPwd ? at line 1 at com.mysql.cj.jdbc.exceptions…

spark3.x新特性

Adaptive Query Execution自适应查询(SparkSQL) 由于缺乏或者不准确的数据统计信息&#xff08;元数据&#xff09;和对成本的错误估算&#xff08;执行计划调度&#xff09;导致生成的初始执行计划不理想 在Spark3.x版本提供Adaptive Query Execution自适应查询技术 通过在”…

数据结构顺序表的初始化,头插,尾插,头删,尾删,指定位置删除,指定位置插入,查找,销毁(详解)

目录 前言顺序表的介绍静态顺序表动态顺序表一.顺序表的初始化二.销毁扩容顺序表打印顺序表三.头插四.尾插五.头删六.尾删七.指定位置之前&#xff08;包括指定位置&#xff09;的插入八.指定位置数据的删除九.查找全部的代码实现总结 前言 数据结构是什么&#xff1f; 数据结…

碘浊度法与红外相机联用测定食品中维生素C

&#x1f31e;欢迎来到看论文的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年4月6日&…

1.微服务

一、微服务是什么 微服务是一种架构风格&#xff0c;即&#xff0c;一个应用应该是一组小型服务&#xff0c;每个服务器只负责一种服务&#xff0c;服务之间可以通过 HTTP 的方式进行互通。每一个功能元素最终都是一个可独立替换和独立升级的软件单元。 可以说&#xff0c;微…

网络编程套接字应用分享【Linux C/C++ 】【UDP应用 | TCP应用 | TCP线程池小项目】

目录 前提知识 1. 理解源ip&#xff0c;目的ip和Macip 2. 端口号 3. 初识TCP&#xff0c;UDP协议 4. 网络字节序 5. socket 编程 sockaddr类型 一&#xff0c;基于udp协议编程 1. socket——创建套接字 2. bind——将套接字强绑定 3. recvfrom——接受数据 4. s…

c++11的重要特性2

可变参数模板在3中。 目录 ​编辑 1、统一的列表初始化&#xff1a; std::initializer_list&#xff1a; std::initializer_list是什么类型&#xff1a; std::initializer_list使用场景&#xff1a; 让模拟实现的vector也支持{}初始化和赋值 2、声明 auto decltype nul…