一、模塊介紹
全球四大衛(wèi)星定位系統(tǒng)
????GPS 系統(tǒng)(美國(guó))
????BDS 系統(tǒng)(中國(guó)北斗)
????GLONASS 系統(tǒng)(俄羅斯)
????伽利略衛(wèi)星導(dǎo)航系統(tǒng)(歐盟)
????ATGM336H-5N 系列模塊是 9.7X10.1 尺寸的高性能 BDS/GNSS 全星座定位導(dǎo)航模塊系列的總稱。該系列模塊產(chǎn)品都是基于中科微第四代低功耗 GNSS SOC 單芯片—AT6558,支持多種衛(wèi)星導(dǎo)航系統(tǒng),包括中國(guó)的 BDS(北斗衛(wèi)星導(dǎo)航系統(tǒng)),美國(guó)的 GPS,俄羅斯GLONASS,歐盟的 GALILEO,日本的 QZSS以及衛(wèi)星增強(qiáng)系統(tǒng) SBAS(WAAS,EGNOS,GAGAN,MSAS)。AT6558 是一款真正意義的六合一多模衛(wèi)星導(dǎo)航定位芯片,包含 32 個(gè)跟蹤通道,可以同時(shí)接收六個(gè)衛(wèi)星導(dǎo)航系統(tǒng)的 GNSS 信號(hào),并且實(shí)現(xiàn)聯(lián)合定位、導(dǎo)航與授時(shí)。
二、使用步驟
????首次使用用usb轉(zhuǎn)ttl連接電腦串口助手,驗(yàn)證模塊能否正常工作,是否定位成功。后續(xù)用stm32串口代替電腦,實(shí)現(xiàn)接收數(shù)據(jù)。
1.數(shù)據(jù)解析
????測(cè)試最好是帶電腦到戶外空曠地進(jìn)行,若是把天線放在陽(yáng)臺(tái)外面的話,有一定幾率定位失敗。空曠地首次定位一般是一分鐘以內(nèi)。
???? 用串口來(lái)看下數(shù)據(jù),波特率默認(rèn)是 9600
????板載 LED 保持一定的頻率閃爍證明定位成功了
????GN、GP、BD 分別代表 雙模模式、GPS 模式、北斗模式
數(shù)據(jù)解析
????例 $GNRMC,084852.000,A,2236.9453,N,11408.4790,E,0.53,292.44,141216,A*75
2.數(shù)據(jù)轉(zhuǎn)換
數(shù)據(jù)格式:
????緯度:ddmm.mmmm 經(jīng)度:dddmm.mmmm
??度分格式 換算成百度 谷歌地圖的格式
北緯 2236.9453 22+(36.9453/60)= 22.615755
東經(jīng) 11408.4790 114+(08.4790/60)=114.141317
??轉(zhuǎn)換成 度分秒的格式
北緯 2236.9453 = 22 度 36 分 0.9453x60 秒 = 22 度 36 分 56.718 秒
東經(jīng) 11408.4790 = 114 度 8 分 0.4790x60 秒 = 114 度 8 分 28.74 秒
三、代碼示例
????思路:gps作為獨(dú)立工作的模塊,stm32端只需編寫(xiě)串口接收函數(shù),接收gps模塊發(fā)來(lái)的數(shù)據(jù)。由于只關(guān)注經(jīng)緯度,故只需解析經(jīng)緯度即可。
????模塊資料里只給了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函數(shù),而不需要選擇use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//標(biāo)準(zhǔn)庫(kù)需要的支持函數(shù)
struct __FILE
{
int handle;
};
FILE __stdout;
//定義_sys_exit()以避免使用半主機(jī)模式
void _sys_exit(int x)
{
x = x;
}
//重定義fputc函數(shù)
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢
USART1->DR = (u8) ch;
return ch;
}
#endif
#if EN_USART1_RX //如果使能了接收
//串口1中斷服務(wù)程序
//注意,讀取USARTx->SR能避免莫名其妙的錯(cuò)誤
u8 USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).
//接收狀態(tài)
//bit15, 接收完成標(biāo)志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字節(jié)數(shù)目
u16 USART_RX_STA=0; //接收狀態(tài)標(biāo)記
//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound){
//GPIO端口設(shè)置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1時(shí)鐘
//串口1對(duì)應(yīng)引腳復(fù)用映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9復(fù)用為USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10復(fù)用為USART1
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9與GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復(fù)用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復(fù)用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//USART1 初始化設(shè)置
USART_InitStructure.USART_BaudRate = bound;//波特率設(shè)置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長(zhǎng)為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無(wú)奇偶校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無(wú)硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
//USART_ClearFlag(USART1, USART_FLAG_TC);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開(kāi)啟相關(guān)中斷
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//搶占優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2; //子優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器、
CLR_Buf();//清空緩存
}
void USART1_IRQHandler(void) //串口1中斷服務(wù)程序
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //讀取接收到的數(shù)據(jù)
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"這一幀數(shù)據(jù)
{
if(Res == '\n')
{
memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memcpy(Save_Data.GPS_Buffer, USART_RX_BUF, point1); //保存數(shù)據(jù)
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) // 串口命令識(shí)別函數(shù)
{
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); //解析錯(cuò)誤
}
else
{
subString++;
if ((subStringNext = strstr(subString, ",")) != NULL)
{
char usefullBuffer[2];
switch(i)
{
case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break; //獲取UTC時(shí)間
case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break; //獲取UTC時(shí)間
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; //獲取經(jīng)度信息
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); //解析錯(cuò)誤
}
}
}
}
}
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 //定義最大接收字節(jié)數(shù) 200
#define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
#define false 0
#define true 1
//定義數(shù)組長(zhǎng)度
#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個(gè)字節(jié).末字節(jié)為換行符
//extern u16 USART_RX_STA; //接收狀態(tài)標(biāo)記
//如果想串口中斷接收,請(qǐng)不要注釋以下宏定義
typedef struct SaveData //存放接收數(shù)據(jù)的結(jié)構(gòu)體
{
char GPS_Buffer[GPS_Buffer_Length];
char isGetData; //是否獲取到GPS數(shù)據(jù)
char isParseData; //是否解析完成
char UTCTime[UTCTime_Length]; //UTC時(shí)間
char latitude[latitude_Length]; //緯度
char N_S[N_S_Length]; //N/S
char longitude[longitude_Length]; //經(jīng)度
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);//設(shè)置系統(tǒng)中斷優(yōu)先級(jí)分組2
delay_init(168); //初始化延時(shí)函數(shù)
uart_init(9600); //GPS使用的串口初始化
LED_Init();
KEY_Init();
clrStruct();
while(1)
{
if(KEY0==0) //按下按鍵獲取一次 直接操作庫(kù)函數(shù)方式讀取IO
{ delay_ms(10);//消抖
if(KEY0==0)
{
LED1=0;
parseGpsBuffer();//獲取位置信息
printGpsBuffer();//發(fā)送位置信息
delay_ms(2000);
LED1=1; //可以借此檢驗(yàn)是否發(fā)送成功
}
}
}
}
如何操作想用的變量
思路:由于接收數(shù)據(jù)被存放到結(jié)構(gòu)體中,訪問(wèn)結(jié)構(gòu)體變量中的內(nèi)容即可。
結(jié)構(gòu)體成員的訪問(wèn)需要借助結(jié)構(gòu)體成員運(yùn)算符——點(diǎn)(.)
c語(yǔ)言中:typedef給結(jié)構(gòu)體起別名
這種方法在實(shí)際操作中用的非常多,在嵌入式開(kāi)發(fā)中幾乎全都是用typedef給結(jié)構(gòu)體起別名方法。比如你常見(jiàn)的STM32單片機(jī)中的程序,就是這樣寫(xiě)的。
typedef struct 結(jié)構(gòu)體名
{
成員列表;
}變量名列表;
例 給結(jié)構(gòu)體模板struct student重新命名為student
// 給結(jié)構(gòu)體模板struct student重新命名為student
typedef struct student
{
char *name; // 學(xué)生名字
int num; // 學(xué)生學(xué)號(hào)
int age; // 學(xué)生年齡
}student;
使用student創(chuàng)建三個(gè)結(jié)構(gòu)體變量student1,student2
student student1 , student2;
我們代碼中定義了一個(gè)結(jié)構(gòu)體模板struct SaveData 重新命名為_(kāi)SaveData。
因此只需用_SaveData創(chuàng)建結(jié)構(gòu)體變量SaveData。Save_Data.xxx即可操作變量。
如:顯示在屏幕上 、給其它變量賦該值
調(diào)用oled的showstring函數(shù)顯示Save_Data.latitude
w=Save_Data.latitude; //緯度文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-822521.html
總結(jié)
????另外附上官方給的F1的工程文件模塊參考例程F1+使用手冊(cè)
????本文介紹了GPS模塊的使用。
????大家有問(wèn)題可以留言,看到了我會(huì)及時(shí)回復(fù)!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-822521.html
到了這里,關(guān)于STM32讀取GPS數(shù)據(jù)-ATGM336H的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!