標(biāo)題:
STM32單片機AIR551G GPS定位程序
[打印本頁]
作者:
Q柒
時間:
2022-12-16 11:39
標(biāo)題:
STM32單片機AIR551G GPS定位程序
合軸551G模塊,移植了正點原子的開發(fā)板程序
STM32單片機源程序如下:
#include "gps.h"
#include "led.h"
#include "SysTick.h"
#include "usart3.h"
#include "stdio.h"
#include "stdarg.h"
#include "string.h"
#include "math.h"
u8 NMEA_Comma_Pos(u8 *buf,u8 cx)
{
u8 *p=buf;
while(cx)
{
if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//遇到'*'或者非法字符,則不存在第cx個逗號
if(*buf==',')cx--;
buf++;
}
return buf-p;
}
//m^n函數(shù)
//返回值:m^n次方.
u32 NMEA_Pow(u8 m,u8 n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
//str轉(zhuǎn)換為數(shù)字,以','或者'*'結(jié)束
//buf:數(shù)字存儲區(qū)
//dx:小數(shù)點位數(shù),返回給調(diào)用函數(shù)
//返回值:轉(zhuǎn)換后的數(shù)值
int NMEA_Str2num(u8 *buf,u8*dx)
{
u8 *p=buf;
u32 ires=0,fres=0;
u8 ilen=0,flen=0,i;
u8 mask=0;
int res;
while(1) //得到整數(shù)和小數(shù)的長度
{
if(*p=='-'){mask|=0X02;p++;}//是負(fù)數(shù)
if(*p==','||(*p=='*'))break;//遇到結(jié)束了
if(*p=='.'){mask|=0X01;p++;}//遇到小數(shù)點了
else if(*p>'9'||(*p<'0')) //有非法字符
{
ilen=0;
flen=0;
break;
}
if(mask&0X01)flen++;
else ilen++;
p++;
}
if(mask&0X02)buf++; //去掉負(fù)號
for(i=0;i<ilen;i++) //得到整數(shù)部分?jǐn)?shù)據(jù)
{
ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');
}
if(flen>5)flen=5; //最多取5位小數(shù)
*dx=flen; //小數(shù)點位數(shù)
for(i=0;i<flen;i++) //得到小數(shù)部分?jǐn)?shù)據(jù)
{
fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');
}
res=ires*NMEA_Pow(10,flen)+fres;
if(mask&0X02)res=-res;
return res;
}
//分析GPGSV信息 可見衛(wèi)星信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf)
{
u8 *p,*p1,dx;
u8 len,i,j,slx=0;
u8 posx;
p=buf;
p1=(u8*)strstr((const char *)p,"$GPGSV");
len=p1[7]-'0'; //得到GPGSV的條數(shù)
posx=NMEA_Comma_Pos(p1,3); //得到可見衛(wèi)星總數(shù)
if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx);
for(i=0;i<len;i++)
{
p1=(u8*)strstr((const char *)p,"$GPGSV");
for(j=0;j<4;j++)
{
posx=NMEA_Comma_Pos(p1,4+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].num=NMEA_Str2num(p1+posx,&dx); //得到衛(wèi)星編號
else break;
posx=NMEA_Comma_Pos(p1,5+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//得到衛(wèi)星仰角
else break;
posx=NMEA_Comma_Pos(p1,6+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到衛(wèi)星方位角
else break;
posx=NMEA_Comma_Pos(p1,7+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx); //得到衛(wèi)星信噪比
else break;
slx++;
}
p=p1+1;//切換到下一個GPGSV信息
}
}
//分析BDGSV信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void NMEA_BDGSV_Analysis(nmea_msg *gpsx,u8 *buf)
{
u8 *p,*p1,dx;
u8 len,i,j,slx=0;
u8 posx;
p=buf;
p1=(u8*)strstr((const char *)p,"$BDGSV");
len=p1[7]-'0'; //得到BDGSV的條數(shù)
posx=NMEA_Comma_Pos(p1,3); //得到可見北斗衛(wèi)星總數(shù)
if(posx!=0XFF)gpsx->beidou_svnum=NMEA_Str2num(p1+posx,&dx);
for(i=0;i<len;i++)
{
p1=(u8*)strstr((const char *)p,"$BDGSV");
for(j=0;j<4;j++)
{
posx=NMEA_Comma_Pos(p1,4+j*4);
if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_num=NMEA_Str2num(p1+posx,&dx); //得到衛(wèi)星編號
else break;
posx=NMEA_Comma_Pos(p1,5+j*4);
if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_eledeg=NMEA_Str2num(p1+posx,&dx);//得到衛(wèi)星仰角
else break;
posx=NMEA_Comma_Pos(p1,6+j*4);
if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_azideg=NMEA_Str2num(p1+posx,&dx);//得到衛(wèi)星方位角
else break;
posx=NMEA_Comma_Pos(p1,7+j*4);
if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_sn=NMEA_Str2num(p1+posx,&dx); //得到衛(wèi)星信噪比
else break;
slx++;
}
p=p1+1;//切換到下一個BDGSV信息
}
}
//分析GNGGA信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void NMEA_GNGGA_Analysis(nmea_msg *gpsx,u8 *buf)
{
u8 *p1,dx;
u8 posx;
p1=(u8*)strstr((const char *)buf,"$GNGGA");
posx=NMEA_Comma_Pos(p1,6); //得到GPS狀態(tài)
if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,7); //得到用于定位的衛(wèi)星數(shù)
if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,8); //水平位置精度
if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,9); //得到海拔高度
if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);
}
//分析GNGSA信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void NMEA_GNGSA_Analysis(nmea_msg *gpsx,u8 *buf)
{
u8 *p1,dx;
u8 posx;
u8 i;
p1=(u8*)strstr((const char *)buf,"$GNGSA");
posx=NMEA_Comma_Pos(p1,2); //得到定位類型
if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);
for(i=0;i<12;i++) //得到定位衛(wèi)星編號
{
posx=NMEA_Comma_Pos(p1,3+i);
if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx);
else break;
}
posx=NMEA_Comma_Pos(p1,15); //得到PDOP位置精度因子
if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,16); //得到HDOP位置精度因子
if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,17); //得到VDOP位置精度因子
if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);
}
//分析GNRMC信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void NMEA_GNRMC_Analysis(nmea_msg *gpsx,u8 *buf)
{
u8 *p1,dx;
u8 posx;
u32 temp;
float rs;
p1=(u8*)strstr((const char *)buf,"$GNRMC");//"$GNRMC",經(jīng)常有&和GNRMC分開的情況,故只判斷GPRMC.
posx=NMEA_Comma_Pos(p1,1); //得到UTC時間
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx); //得到UTC時間,去掉ms
gpsx->utc.hour=temp/10000;
gpsx->utc.min=(temp/100)%100;
gpsx->utc.sec=temp%100;
}
posx=NMEA_Comma_Pos(p1,3); //得到緯度
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
gpsx->latitude=temp/NMEA_Pow(10,dx+2); //得到°
rs=temp%NMEA_Pow(10,dx+2); //得到'
gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//轉(zhuǎn)換為°
}
posx=NMEA_Comma_Pos(p1,4); //南緯還是北緯
if(posx!=0XFF)gpsx->nshemi=*(p1+posx);
posx=NMEA_Comma_Pos(p1,5); //得到經(jīng)度
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
gpsx->longitude=temp/NMEA_Pow(10,dx+2); //得到°
rs=temp%NMEA_Pow(10,dx+2); //得到'
gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//轉(zhuǎn)換為°
}
posx=NMEA_Comma_Pos(p1,6); //東經(jīng)還是西經(jīng)
if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);
posx=NMEA_Comma_Pos(p1,7); //獲取地面速度
if(posx!=0XFF)gpsx->lspeed=*(p1+posx);
posx=NMEA_Comma_Pos(p1,9); //得到UTC日期
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx); //得到UTC日期
gpsx->utc.date=temp/10000;
gpsx->utc.month=(temp/100)%100;
gpsx->utc.year=2000+temp%100;
}
}
//分析GNVTG信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void NMEA_GNVTG_Analysis(nmea_msg *gpsx,u8 *buf)
{
u8 *p1,dx;
u8 posx;
p1=(u8*)strstr((const char *)buf,"$GNVTG");
posx=NMEA_Comma_Pos(p1,7); //得到地面速率
if(posx!=0XFF)
{
gpsx->speed=NMEA_Str2num(p1+posx,&dx);
if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx); //確保擴大1000倍
}
}
//提取NMEA-0183信息
//gpsx:nmea信息結(jié)構(gòu)體
//buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址
void GPS_Analysis(nmea_msg *gpsx,u8 *buf)
{
NMEA_GPGSV_Analysis(gpsx,buf); //GPGSV解析
NMEA_BDGSV_Analysis(gpsx,buf); //BDGSV解析
NMEA_GNGGA_Analysis(gpsx,buf); //GNGGA解析
NMEA_GNGSA_Analysis(gpsx,buf); //GPNSA解析
NMEA_GNRMC_Analysis(gpsx,buf); //GPNMC解析
NMEA_GNVTG_Analysis(gpsx,buf); //GPNTG解析
}
/**********************************
功能:發(fā)送數(shù)據(jù)到GPS模塊
日期:2022.12.14
參數(shù):cmd AT命令
返回值: 無
*****************************/
void SendAtToGps(u8 *cmd)
{
while (*cmd !='\0')
{
USART_SendData(USART3,*cmd++);
while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==Bit_RESET);
}
}
/****************************
功能:檢查GPS模塊應(yīng)答是否符合預(yù)期
日期:2022.12.14
參數(shù):str 正確應(yīng)答
返回值:無
***************************/
u8 GpsAckChack(u8 *str)
{
//u8 str[225];
delay_ms(500);
if(USART3_RX_STA !=0)
{
USART3_RX_STA=0;
if(strstr ((const char*)USART3_RX_BUF,(const char*)str))
{
memset(USART3_RX_BUF,0, sizeof USART3_RX_BUF); //符合預(yù)期
return 0;
}
else
{
memset(USART3_RX_BUF,0, sizeof USART3_RX_BUF); //不符合預(yù)期
return 1;
//清空數(shù)組
}
}
else
{
memset(USART3_RX_BUF,0, sizeof USART3_RX_BUF);
return 1;
}
}
/*********************************************
功能:GPS模塊初始化
日期:2022.12.14
參數(shù): 無
返回值:無
*********************************************/
void Gps_Init()
{
cmd1:SendAtToGps (ColdStart); //發(fā)送冷啟動指令
delay_ms(50);
if(!GpsAckChack ("$GNTXT,GK9701*7E..$GNTXT,HW:V190"));
else goto cmd1;
cmd2:SendAtToGps (GPSL1L5); //全系統(tǒng)模式
delay_ms(50);
if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190")) ;
else goto cmd2;
cmd3:SendAtToGps(OpenSBAS); //開啟SBAS 功能
delay_ms(50);
if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190")) ;
else goto cmd3;
cmd4:SendAtToGps(delay1sNMEA); //配置輸出 NMEA 消息的間隔 1s
delay_ms(50);
if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190")) ;
else goto cmd4;
cmd5:SendAtToGps(EnableRMC); //設(shè)置 NMEA 語句輸出使能 使能RMC
delay_ms(50);
if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190")) ;
else goto cmd5;
SendAtToGps(MoreFast);//加速定位信息
}
復(fù)制代碼
51hei.png
(7.85 KB, 下載次數(shù): 49)
下載附件
2022-12-17 04:40 上傳
Keil代碼下載:
AIR551G.7z
(6.28 MB, 下載次數(shù): 18)
2022-12-17 04:40 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1