文章目录

一、模块介绍二、使用步骤1.数据解析2.数据转换

三、代码示例总结

一、模块介绍

全球四大卫星定位系统     GPS 系统(美国)     BDS 系统(中国北斗)     GLONASS 系统(俄罗斯)     伽利略卫星导航系统(欧盟)     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串口代替电脑,实现接收数据。

1.数据解析

    测试最好是带电脑到户外空旷地进行,若是把天线放在阳台外面的话,有一定几率定位失败。空旷地首次定位一般是一分钟以内。      用串口来看下数据,波特率默认是 9600     板载 LED 保持一定的频率闪烁证明定位成功了     GN、GP、BD 分别代表 双模模式、GPS 模式、北斗模式

数据解析     例 $GNRMC,084852.000,A,2236.9453,N,11408.4790,E,0.53,292.44,141216,A*75

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。 因此只需用_SaveData创建结构体变量SaveData。Save_Data.xxx即可操作变量。 如:显示在屏幕上 、给其它变量赋该值

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

总结

    另外附上官方给的F1的工程文件模块参考例程F1+使用手册     本文介绍了GPS模块的使用。     大家有问题可以留言,看到了我会及时回复!

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: