基於STM32的GPS模塊驅動(AIR530)

一、概述

         由於做項目要用到GPS定位,於是在某寶購買了這款GPS模塊。項目採用的MCU是STM32。廢話少說,進入正題。

二、GPS模塊簡介

        Air530 模塊是一款高性能、高集成度的多模衛星定位導航模塊。體積小、功耗低,可用於車載導 航、智能穿戴、無人機等 GNSS 定位的應用中。而且提供了和其他模塊廠商兼容的軟、硬件接口,大幅 減少了用戶的開發週期。 模塊支持GPS/Beidou/GLONASS/Galileo/QZSS/SBAS。採用了射頻基帶一體化設計,集成了 DC/DC、 LDO、 LNA、射頻前端、基帶處理、32 位 RISC CPU、RAM、FLASH 存儲、RTC 和電源管理等功能。提供 超高的性能,即使在弱信號的地方,也能快速、準確的定位。

這個模塊有五個引腳。如果只是簡單的定位玩一下的話,那個1pps引腳不用也可以。

 VDD       供電電源,電壓輸入 範圍 3.3V-5.5V

 TXD       GPS 串口數據輸出, 2.8V--5V 自適應

RXD       GPS 串口數據輸入, 2.8V--5V 自適應

1PPS      One plus per second(2.8V)

GND      接地

三、STM32驅動程序編寫

 1.NMEA協議

       在編寫驅動程序前一定要知道NMEA協議。NMEA是(National Marine Electronics Association )爲海用電子設備制定的標準格式。NMEA縮寫,同時也是數據傳輸標準工業協會,在這裏,實際上應爲NMEA 0183。它是一套定義接收機輸出的標準信息,有幾種不同的格式,每種都是獨立相關的ASCII格式,逗點隔開數據流,數據流長度從30-100字符不等,通常以每秒間隔選擇輸出,最常用的格式爲"GGA",它包含了定位時間,緯度,經度,高度,定位所用的衛星數,DOP值,差分狀態和校正時段等,其他的有速度,跟蹤,日期等。NMEA實際上已成爲所有的GPS接收機和最通用的數據輸出格式,同時它也被用於與GPS接收機接口的大多數的軟件包裏。NMEA-0183協議定義的語句非常多,但是常用的或者說兼容性最廣的語句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。

       AIR530 模塊支持 NMEA 0183 V4.1 協議併兼容以前版本,關於 NMEA 0183 V4.1 的詳細信息請參照 NMEA 0183 V4.1 官方文檔。

        GGA:時間、位置、衛星數量

        GLL:經度、緯度、 UTC 時間

        GSA:GPS 接收機操作模式,定位使用的衛星,DOP 值,定位狀態

        GSV:可見 GPS 衛星信息、仰角、方位角、信噪比

        RMC:時間、日期、位置、速度 VTG:地面速度信息

 2.驅動開發

gps頭文件

/*****************************************************
消息 :$GPRMC,100646.000,A,3109.9704,N,12123.4219,E,0.257,335.62,291216,,,A*59
ID :            $GPRMC RMC                  協議頭
UTC時間:         100646.000                  hhmmss.sss
狀態:            A                           A=數據有效;V=數據無效
緯度 :           2109.9704                   ddmm.mmmm
N/S:              N                          N=北,S=南
經度:           11123.4219                   dddmm.mmmm
E/W :             E                          W=西,E=東
地面速度:        0.257                        Knot(節)
方位:           335.62                        度
日期            291216                        ddmmyy
磁變量           無
校驗和           *59
<CR><LF>                                     消息結束
******************************************************/
#ifndef __GPS__H
#define __GPS__H
#include "sys.h"
#include "usart.h"
#include "stdint.h"
#include "string.h"
#include "stdlib.h"
//啓動命令

#define  HotStart     "$PGKC030,1,1*2C\r\n"      //Gps系統熱啓動
#define  WarmStart    "$PGKC030,2,1*2F\r\n"      //Gps系統溫啓動
#define  ColdStart    "$PGKC030,3,1*2E\r\n"      //Gps系統冷啓動
#define  ReColdStart  "$PGKC030,4,1*29\r\n"      //Gps系統重置冷啓動

// 衛星定位模式設置
#define  SingleGps    "$PGKC115,1,0,0,0*2B\r\n"      //單 GPS
#define  GPSandBEIDOU   "$PGKC115,1,0,1,0*2A\r\n"      //GPS+BEIDOU
#define  GPSandGLONASS  "$PGKC115,1,1,0,0*2A\r\n"      //GPS+GLONASS

// 低功耗模式設置       
#define  LPsleep  "$PGKC051,1*36\r\n"    //  sleep 模式     
#define  LPstop   "$PGKC051,0*37\r\n"    //  stop 模式 

/******************************************
//配置輸出 NMEA 消息的間隔(ms 單位)  
Arg1: 200-10000
******************************************/
#define  delay1sNMEA  "$PGKC101,1000*02\r\n" // 間隔1ms


/******************************************
//開啓或關閉 QZSS NMEA格式輸出  
Arg1: “0”,關閉
      “1”,開啓
******************************************/
#define  OpenNMEA    "$PGKC113,1*31\r\n"
#define  CloseNMEA   "$PGKC113,0*30\r\n"


//設置 NMEA 輸出波特率
#define  SetBps115200   "$PGKC147,115200*06\r\n"
//加速定位信息
#define  MoreFast   "$PGKC639,34.093145,108.542323,0,2019,05,04,02,43,54*05\r\n"

/*******************************************
設置 NMEA 語句輸出使能
Arg1: GLL “0”,關閉; “1”,打開
Arg2: RMC “0”,關閉; “1”,打開
Arg3: VTG “0”,關閉; “1”,打開
Arg4: GGA “0”,關閉; “1”,打開
Arg5: GSA “0”,關閉; “1”,打開
Arg6: GSV “0”,關閉; “1”,打開
Arg7: GRS “0”,關閉; “1”,打開
Arg8: GST “0”,關閉; “1”,打開
Arg9~ Arg19: 保留
*******************************************/
#define  EnableRMC   "$PGKC242,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*36\r\n"


//擦除 flash 中的輔助定位數據
#define  DeleteFlash   "$PGKC040*2B\r\n"


//開啓或關閉 SBAS 功能
#define  CloseSBAS   "$PGKC239,1*3A\r\n"//關閉SBAS 功能
#define  OpenSBAS   "$PGKC239,0*3B\r\n"//開啓SBAS 功能

//RMC_DATA結構體
typedef struct RMC_DATA{
	char    time[12];  //UTC時間
	char    state[12]; //狀態 
  char	  lat[12];  //緯度
	char    NS[2];    //N/S指示
	char    WE[2];     //W/E指示
	char	  lng[12];  //經度
	char    date[12];  //日期
}rmc_data;
//錯誤信息上傳數據幀
typedef struct WARNING{
	char start;//幀頭
	u8 WarningFlag;//從最低位到最高爲分別表示:電池電量警告,GPS定位失敗警告,電子圍欄越界警告,跌倒警告,其他暫時預留。
	 char end;//結束標誌
}Warning;
//定位信息上傳數據幀
typedef struct OPSITIONDATA{
  char    start;
	char    time[12];  //UTC時間
	char    state[12]; //狀態 
  char	  lat[12];  //緯度
	char    NS[2];    //N/S指示
	char	  lng[12];  //經度	
	char    WE[2];     //W/E指示
	char    date[12];  //日期
  char     end;
}OpsitionData;
//心率信息上傳數據幀
typedef struct HEARTRATEDATA{
	char start;
  u8   HeartRate;//心率次數
	 char end;
}HeartRateData;

extern rmc_data  RecRMC; 
extern rmc_data * const pRecRMC; //RMC解析輸出緩存區,該指針指向固定的地址
void SendAtToGps(u8 *cmd);
u8   GpsAckChack(u8 *str);
void Gps_Init(void);
void AnalysisRMC(rmc_data *pRecRMC);
void GpsRMCdataShow(void);
u8 OverStepArea(rmc_data *pRecRMC);
void mixGpsdate(char * ULdate,rmc_data *pRecRMC);
#endif

GPS驅動函數

#include "gps.h"
/*************************************
功能:發送數據到Gps模塊
作者:賀遠
日期:2019.03.05
參數:cmd  AT命令
返回值:無
**************************************/
void SendAtToGps(u8 *cmd)
{
	while(*cmd!='\0')
	{
	 USART_SendData(USART1,*cmd++);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==Bit_RESET);	//發送數據結束
	}
}
/*************************************
功能://檢查GPS模塊應答是否符合預期
作者:賀遠
日期:2019.03.05
參數:str  正確的應答
返回值:無
**************************************/
u8 GpsAckChack(u8 *str)
{
		//u8 str[225];
	  delay_ms(500);
		if(USART1_RX_STA!=0)
		{
			 USART1_RX_STA=0;
			   
			 if(strstr((const char*)USART1_RX_BUF,(const char*)str)) { memset(USART1_RX_BUF,0, sizeof USART1_RX_BUF);        return 0;}//符合預期
			 else                                                    { memset(USART1_RX_BUF,0, sizeof USART1_RX_BUF);     return 1;}//不符合預期      
                                //清空數組  			
		} 
		else { memset(USART1_RX_BUF,0, sizeof USART1_RX_BUF);   return  1;}
}
/*************************************
功能:Gps模塊初始化
作者:賀遠
日期:2019.03.05
參數:無
返回值:無
**************************************/
void Gps_Init()
{
	cmd1:SendAtToGps(ColdStart);   //GPS冷啓動
       delay_ms(50);	
	     if (!GpsAckChack("$PGKC001,30,3*1E"))  ; 
	     else goto  cmd1;
	cmd2:SendAtToGps(GPSandBEIDOU);//GPS+BEIDOU
       delay_ms(50);	
	     if (!GpsAckChack("$PGKC001,115,3,1,0,0,0,1,49*15"))  ; 
	     else goto  cmd2;

	cmd3:SendAtToGps(OpenSBAS);    //開啓SBAS 功能
	     delay_ms(50);	
			 if (!GpsAckChack("$PGKC001,239,3*25"))  ; 
	     else goto  cmd3;
	cmd4:SendAtToGps(delay1sNMEA); //配置輸出 NMEA 消息的間隔 1s
       delay_ms(50);	
	     if (!GpsAckChack("$PGKC001,101,3*2D"))  ; 
	     else goto  cmd4;
	cmd5:SendAtToGps(EnableRMC);   //設置 NMEA 語句輸出使能  使能RMC
       delay_ms(50);	
	     if (!GpsAckChack("$PGKC001,242,3*29"))  ; 
	     else goto  cmd5;
       
			 SendAtToGps(MoreFast);//加速定位信息


}
rmc_data  RecRMC; 
rmc_data * const pRecRMC=&RecRMC; //RMC解析輸出緩存區,該指針指向固定的地址
/*************************************
功能:GPSRMC數據解析
作者:賀遠
日期:2019.03.09
參數:無
返回值:無
**************************************/
void AnalysisRMC(rmc_data *pRecRMC)//GPSRMC數據解析
{
	int i,n=0;
	if(USART1_RX_STA!=0)
		{
			 USART1_RX_STA=0;
			 for(i=0;USART1_RX_BUF[i]!='\0';i++)
			 {
				 if(USART1_RX_BUF[i]==',')  
				 {
					 n++;
					 i++;// 跳過 “,”
				 //strncpy(sub, string+12,13);   將string從string[12]開始,截取13個複製到sub中
				 if(n==1)  { strncpy(pRecRMC->time,  USART1_RX_BUF+i,10); 	i=i+9; }//i=i+10;目的是爲了減少循環次數,提高效率
				 if(n==2)  { strncpy(pRecRMC->state, USART1_RX_BUF+i,1);           }
				 if(n==3)  { strncpy(pRecRMC->lat,   USART1_RX_BUF+i,9);    i=i+8; }  
				 if(n==4)  { strncpy(pRecRMC->NS,    USART1_RX_BUF+i,1); 				   }
				 if(n==5)  { strncpy(pRecRMC->lng,   USART1_RX_BUF+i,10);   i=i+9; }
				 if(n==6)  { strncpy(pRecRMC->WE,    USART1_RX_BUF+i,1);           }
				 if(n==9)  { strncpy(pRecRMC->date,  USART1_RX_BUF+i,6);    i=i+5; }
			  }
			 }
		 }
    memset(USART1_RX_BUF,0, sizeof USART1_RX_BUF);    //清空接收緩存區 			
	
	
}
/*************************************
功能:GPS解析數據顯示
作者:賀遠
日期:2019.03.09
參數:無
返回值:無
**************************************/

//void GpsRMCdataShow()

//{
//delay_ms(400);	
//		 AnalysisRMC(pRecRMC);
//		
//		 LCD_ShowString(10,70,250,16,16,"UTC  :");
//		 LCD_ShowString(60,70,250,16,16, (u8*)pRecRMC->time);
//		
//		 LCD_ShowString(10,90,250,16,16,"state:");
//		 LCD_ShowString(60,90,250,16,16,(u8*)pRecRMC->state);
//		
//		 LCD_ShowString(10,110,250,16,16,"lat  :");
//		 LCD_ShowString(60,110,250,16,16,(u8*)pRecRMC->lat);
//		 LCD_ShowString(150,110,250,16,16,(u8*)pRecRMC->NS);
//		
//		 LCD_ShowString(10,130,250,16,16,"lng  :");
//		 LCD_ShowString(60,130,250,16,16,(u8*)pRecRMC->lng);
//		 LCD_ShowString(150,130,250,16,16,(u8*)pRecRMC->WE);
//		
// 	   LCD_ShowString(10,150,250,16,16,"date :");
//	   LCD_ShowString(60,150,250,16,16,(u8*)pRecRMC->date);
//		 memset(pRecRMC,0, sizeof pRecRMC);    //清空接收緩存區 	
//}
/*************************************
功能:GPS電子圍欄超出檢測
作者:賀遠
日期:2019.03.10
參數:無
返回值:0/1
**************************************/
u8 OverStepArea(rmc_data *pRecRMC)
{
	float a,b,c,a1=3415.2645,b1=10925.2235,c1;
	a=atof(pRecRMC->lat); //字符串轉float
	b=atof(pRecRMC->lng);
	c=(a-a1)*(a-a1)+(b-b1)*(b-b1);
	c1=0.5555*0.5555+0.6666*0.6666;//圓形區域
  if(c1>=c) return 0;//未越界
	else return 1;
}
/*************************************
功能:GPS定位信息上傳數據組幀
作者:賀遠
日期:2019.03.10
參數:無
返回值:無
說明:char *strcat(char *dest, const char *src);
      strcat() 會將參數 src 字符串複製到參數 dest 所指的字符串尾部;
      dest 最後的結束字符 NULL 會被覆蓋掉,並在連接後的字符串的尾部再增加一個 NULL。
**************************************/
void mixGpsdate(char * ULGpsdate,rmc_data *pRecRMC)
{
	ULGpsdate=strcat(ULGpsdate,pRecRMC->date);
	ULGpsdate=strcat(ULGpsdate,pRecRMC->time);
	ULGpsdate=strcat(ULGpsdate,pRecRMC->state);
	ULGpsdate=strcat(ULGpsdate,pRecRMC->lat);
	ULGpsdate=strcat(ULGpsdate,pRecRMC->NS);
	ULGpsdate=strcat(ULGpsdate,pRecRMC->lng);
	ULGpsdate=strcat(ULGpsdate,pRecRMC->WE);
	
}







 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章