STM32读取GPS数据-ATGM336H

这篇具有很好参考价值的文章主要介绍了STM32读取GPS数据-ATGM336H。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、模块介绍

全球四大卫星定位系统
    GPS 系统(美国)
    BDS 系统(中国北斗)
    GLONASS 系统(俄罗斯)
    伽利略卫星导航系统(欧盟)
atgm336h,stm32笔记,stm32,单片机,模块测试
    ATGM336H-5N 系列模块是 9.7X10.1 尺寸的高性能 BDS/GNSS 全星座定位导航模块系列的总称。该系列模块产品都是基于中科微第四代低功耗 GNSS SOC 单芯片—AT6558,支持多种卫星导航系统,包括中国的 BDS(北斗卫星导航系统),美国的 GPS,俄罗斯GLONASS,欧盟的 GALILEO,日本的 QZSS以及卫星增强系统 SBAS(WAAS,EGNOS,GAGAN,MSAS)。AT6558 是一款真正意义的六合一多模卫星导航定位芯片,包含 32 个跟踪通道,可以同时接收六个卫星导航系统的 GNSS 信号,并且实现联合定位、导航与授时。

二、使用步骤

    首次使用用usb转ttl连接电脑串口助手,验证模块能否正常工作,是否定位成功。后续用stm32串口代替电脑,实现接收数据。
atgm336h,stm32笔记,stm32,单片机,模块测试

1.数据解析

    测试最好是带电脑到户外空旷地进行,若是把天线放在阳台外面的话,有一定几率定位失败。空旷地首次定位一般是一分钟以内。
     用串口来看下数据,波特率默认是 9600

    板载 LED 保持一定的频率闪烁证明定位成功了
    GN、GP、BD 分别代表 双模模式、GPS 模式、北斗模式
atgm336h,stm32笔记,stm32,单片机,模块测试

数据解析
    例 $GNRMC,084852.000,A,2236.9453,N,11408.4790,E,0.53,292.44,141216,A*75
atgm336h,stm32笔记,stm32,单片机,模块测试

2.数据转换

数据格式:
    纬度:ddmm.mmmm 经度:dddmm.mmmm
  度分格式 换算成百度 谷歌地图的格式
北纬 2236.9453 22+(36.9453/60)= 22.615755
东经 11408.4790 114+(08.4790/60)=114.141317
  转换成 度分秒的格式
北纬 2236.9453 = 22 度 36 分 0.9453x60 秒 = 22 度 36 分 56.718 秒
东经 11408.4790 = 114 度 8 分 0.4790x60 秒 = 114 度 8 分 28.74 秒

三、代码示例

    思路:gps作为独立工作的模块,stm32端只需编写串口接收函数,接收gps模块发来的数据。由于只关注经纬度,故只需解析经纬度即可。

    模块资料里只给了F1的例程,这里放改完的F4的代码吧。
gps.c

#include "sys.h"
#include "gps.h"	
char rxdatabufer;
u16 point1 = 0;
_SaveData Save_Data;
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif
//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif
 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	

//初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound){
   //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
 
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
	
	//USART1端口配置
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    USART_Init(USART1, &USART_InitStructure); //初始化串口1
    USART_Cmd(USART1, ENABLE);  //使能串口1 
	
	//USART_ClearFlag(USART1, USART_FLAG_TC);
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
	//Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
    CLR_Buf();//清空缓存
}

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
	if(Res == '$')
	{
		point1 = 0;	
	}
	  USART_RX_BUF[point1++] = Res;

	if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C')			//确定是否收到"GPRMC/GNRMC"这一帧数据
	{
		if(Res == '\n')									   
		{
			memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length);      //清空
			memcpy(Save_Data.GPS_Buffer, USART_RX_BUF, point1); 	//保存数据
			Save_Data.isGetData = true;
			point1 = 0;
			memset(USART_RX_BUF, 0, USART_REC_LEN);      //清空				
		}			
	}
	if(point1 >= USART_REC_LEN)
	{
		point1 = USART_REC_LEN;
	}	
		 		 
   } 
}


u8 Hand(char *a)                   // 串口命令识别函数
{ 
    if(strstr(USART_RX_BUF,a)!=NULL)
	    return 1;
	else
		return 0;
}

void CLR_Buf(void)                           // 串口缓存清理
{
	memset(USART_RX_BUF, 0, USART_REC_LEN);      //清空
  point1 = 0;                    
}

void clrStruct()
{
	Save_Data.isGetData = false;
	Save_Data.isParseData = false;
	Save_Data.isUsefull = false;
	memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length);      //清空
	memset(Save_Data.UTCTime, 0, UTCTime_Length);
	memset(Save_Data.latitude, 0, latitude_Length);
	memset(Save_Data.N_S, 0, N_S_Length);
	memset(Save_Data.longitude, 0, longitude_Length);
	memset(Save_Data.E_W, 0, E_W_Length);
	
}
void errorLog(int num)
{
	
	while (1)
	{
	  	printf("ERROR%d\r\n",num);
	}
}

void parseGpsBuffer()
{
	char *subString;
	char *subStringNext;
	char i = 0;
	if (Save_Data.isGetData)
	{
		Save_Data.isGetData = false;
		//printf("**************\r\n");
	//	printf(Save_Data.GPS_Buffer);

		
		for (i = 0 ; i <= 6 ; i++)
		{
			if (i == 0)
			{
				if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
					errorLog(1);	//解析错误
			}
			else
			{
				subString++;
				if ((subStringNext = strstr(subString, ",")) != NULL)
				{
					char usefullBuffer[2]; 
					switch(i)
					{
						case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break;	//获取UTC时间
						case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break;	//获取UTC时间
						case 3:memcpy(Save_Data.latitude, subString, subStringNext - subString);break;	//获取纬度信息
						case 4:memcpy(Save_Data.N_S, subString, subStringNext - subString);break;	//获取N/S
						case 5:memcpy(Save_Data.longitude, subString, subStringNext - subString);break;	//获取经度信息
						case 6:memcpy(Save_Data.E_W, subString, subStringNext - subString);break;	//获取E/W

						default:break;
					}

					subString = subStringNext;
					Save_Data.isParseData = true;
					if(usefullBuffer[0] == 'A')
						Save_Data.isUsefull = true;
					else if(usefullBuffer[0] == 'V')
						Save_Data.isUsefull = false;

				}
				else
				{
					errorLog(2);	//解析错误
				}
			}
		}
	}
}

void printGpsBuffer()
{
	if (Save_Data.isParseData)
	{
		Save_Data.isParseData = false;
		
		printf("Save_Data.UTCTime = ");
		printf(Save_Data.UTCTime);
		printf("\r\n");

		if(Save_Data.isUsefull)
		{
			Save_Data.isUsefull = false;
			printf("Save_Data.latitude = ");
			printf(Save_Data.latitude);
			printf("\r\n");


			printf("Save_Data.N_S = ");
			printf(Save_Data.N_S);
			printf("\r\n");

			printf("Save_Data.longitude = ");
			printf(Save_Data.longitude);
			printf("\r\n");

			printf("Save_Data.E_W = ");
			printf(Save_Data.E_W);
			printf("\r\n");
		}
		else
		{
			printf("GPS DATA is not usefull!\r\n");
		}
		
	}
}

#endif	

gps.h

#ifndef __gps_H
#define __gps_H
#include "stdio.h"	
#include "stm32f4xx_conf.h"
#include "sys.h" 
#include "string.h"
 	
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
#define false 0
#define true 1  
//定义数组长度
#define GPS_Buffer_Length 80
#define UTCTime_Length 11
#define latitude_Length 11
#define N_S_Length 2
#define longitude_Length 12
#define E_W_Length 2 	
//extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
//extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义

typedef struct SaveData //存放接收数据的结构体
{
	char GPS_Buffer[GPS_Buffer_Length];
	char isGetData;		//是否获取到GPS数据
	char isParseData;	//是否解析完成
	char UTCTime[UTCTime_Length];		//UTC时间
	char latitude[latitude_Length];		//纬度
	char N_S[N_S_Length];		//N/S
	char longitude[longitude_Length];		//经度
	char E_W[E_W_Length];		//E/W
	char isUsefull;		//定位信息是否有效
} _SaveData;


void errorLog(int num);
void parseGpsBuffer(void);
void printGpsBuffer(void);

void uart_init(u32 bound);
extern char rxdatabufer;
extern u16 point1;
extern _SaveData Save_Data;

void CLR_Buf(void);
u8 Hand(char *a);
void clrStruct(void);
#endif

main.c


#include "sys.h"
#include "delay.h"
#include "gps.h"
#include "led.h"
#include "key.h"
//-----------------------------------------------------------------------//
// 模块         stm32
//GPS  TX-->PA10 pa9 USART1 
//------------------------------------------------------------------------//

int main(void)
{

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);      //初始化延时函数
    uart_init(9600);  //GPS使用的串口初始化  
    LED_Init();
    KEY_Init();
	clrStruct();
	while(1)
	{ 
	 if(KEY0==0) //按下按键获取一次 直接操作库函数方式读取IO
	  { delay_ms(10);//消抖
       if(KEY0==0)
	   {
	   LED1=0;
	   parseGpsBuffer();//获取位置信息
       printGpsBuffer();//发送位置信息
	   delay_ms(2000);
	   LED1=1; //可以借此检验是否发送成功
     }
  	}
}
}

如何操作想用的变量
思路:由于接收数据被存放到结构体中,访问结构体变量中的内容即可。
结构体成员的访问需要借助结构体成员运算符——点(.)
c语言中:typedef给结构体起别名

这种方法在实际操作中用的非常多,在嵌入式开发中几乎全都是用typedef给结构体起别名方法。比如你常见的STM32单片机中的程序,就是这样写的。

 typedef struct 结构体名
{
  成员列表;
}变量名列表;

例 给结构体模板struct student重新命名为student


// 给结构体模板struct student重新命名为student
typedef struct student
{
    char *name;  // 学生名字
    int num;     // 学生学号
    int age;     // 学生年龄
}student;

使用student创建三个结构体变量student1,student2

student  student1 , student2; 

我们代码中定义了一个结构体模板struct SaveData 重新命名为_SaveData。
atgm336h,stm32笔记,stm32,单片机,模块测试
因此只需用_SaveData创建结构体变量SaveData。Save_Data.xxx即可操作变量。
atgm336h,stm32笔记,stm32,单片机,模块测试
如:显示在屏幕上 、给其它变量赋该值

调用oled的showstring函数显示Save_Data.latitude
w=Save_Data.latitude; //纬度

总结

    另外附上官方给的F1的工程文件模块参考例程F1+使用手册
    本文介绍了GPS模块的使用。
    大家有问题可以留言,看到了我会及时回复!文章来源地址https://www.toymoban.com/news/detail-822521.html

到了这里,关于STM32读取GPS数据-ATGM336H的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用STM32CubeProgrammer工具读取单片机Flash数据读取

    本文主要介绍,如何使用STM32CubeProgrammer工具读取和写入单片机Flash内部的数据,方便调试使用。 2.1 连接Stlink和单片机,点击“connect”进行连接 2.2 读取固定长度的数据 根据程序的大小,设置需要读取的字节数,如下图所示。点击“read”将单片机Flash中的数据读取到STM32Cube

    2024年02月12日
    浏览(44)
  • STM32学习笔记———几种简单传感器的数据读取

    传感器正如计算机的眼睛。从广义上讲,传感器就是一种能感知外界信息,并将这些信息按照一定规律转换成可用的电信号或其他形式的输出信号的装置,达到对信息的存储,传输,控制的目的。本文着重分析如何通过单片机分析电信号时序图实现对传感器的控制与传感器采

    2023年04月23日
    浏览(45)
  • 【单片机】DS2431,STM32,EEPROM读取与写入

    芯片介绍: https://qq742971636.blog.csdn.net/article/details/132164189 DS2431内部有128个字节的数据,这篇博客可以对这128个字节的数据进行读写,而有的人想要改写芯片ROM,这是芯片的唯一地址,请看这里 https://blog.csdn.net/x1131230123/article/details/135667146 接线 串口结果: 部分代码: 代码:

    2024年02月13日
    浏览(46)
  • 【单片机】STM32单片机读取旋转编码器,TIM定时器编码器模式捕获,程序

    旋转编码器简单来说,就是会输出2个PWM,依据相位可以知道旋转方向,依据脉冲个数可以知道旋转的角度。一般旋转一圈有一个固定数值的脉冲个数。 旋转编码器广泛用于电机、或者角度传感器,STM32的定时器可以直接接入这两个波形获取到信息。 前两个引脚(接地和Vcc)

    2024年02月13日
    浏览(50)
  • stm32 m5311上传gps数据上onenet云平台实现地图定位

    新手,第一次写博客,如有不足请大家见谅并指出。下面开始正文。 本文是帮一个朋友做一个NB_Iot的小东西这个过程的学习记录吧。 NB模块是M5311,然后还有一个stm32f103的最小系统开发板,后面开始了漫漫学习NB模块上云的道路。M5311我搜到的例程都是用onenet平台,自然而然地

    2023年04月08日
    浏览(86)
  • STM32初学入门笔记(3):STM32CubeMX配置STM32实现多通道ADC+DMA读取模拟量

    模拟信号的读取是我们在做很多项目是都要用到的,而模拟量的读取就要依赖于ADC数模转换器。对于初学者,学习使用ADC可以很大的帮助以后的STM32学习。 目录 ADC简介 : DMA简介:  工程开始: STM32CubeMX配置区: 配置外部时钟: 配置调试: 配置ADC: 配置DMA: 配置串口: 配

    2024年02月09日
    浏览(51)
  • STM32单片机入门学习笔记——MPU6050

    笔记整理自B站UP主江科大自化协教程《[10-2] MPU6050简介_哔哩哔哩_bilibili》,所用单片机也为教程推荐单片机。 如果芯片里再集成一个3轴的磁场传感器,测量XYZ轴的磁场强度,那就叫做9轴姿态传感器,如果再集成一个气压传感器,测量气压大小,那就叫做10轴姿态传感器,一

    2024年02月08日
    浏览(52)
  • stm32 笔记 UART读取及HAL库应用

     由此图可知: 采用HAL库,中断方式接收串口,只有当RxXferCount == 0 时,也就是调用这个函数,接收指定量的数据大小完成时,才会调用回调函数HAL_UART_RxCpltCallback()。 而且,RxXferCount == 0 后,也会使得中断退出,此时需要从新设置 HAL_UART_Receive_IT() 开启中断。 这里还需要注意

    2024年02月15日
    浏览(50)
  • STM32L+BC20+MQTT协议传输温湿度,GPS数据到阿里云物联网平台

    (阿里云)STM32L+BC20+MQTT协议传输温湿度,GPS数据到阿里云物联网 1、材料准备 准备以下材料 2、设备连接 2.1 插入物联网卡 首先把BC20核心板从开发板上拆下来 然后将物联卡放置在BC20核心板内 物联卡放置完成将BC20核心板重新插入到开发板内(注意不要弄错方向) 同时接入天

    2024年02月15日
    浏览(56)
  • STM32单片机入门学习笔记——定时器TIM第二部分

    笔记整理自B站UP主 江科大自化协 教程 《STM32入门教程-2023持续更新中》 ,所用单片机也为教程推荐单片机。 第一部分:定时器基本定时的功能,定时器每隔这个时间产生一个中断,来实现每隔一个固定时间执行一段程序的目的,比如要做一个时钟、秒表或者使用一些程序算

    2024年02月08日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包