STM32读取GPS(北斗)数据驱动程序

本文博客链接:https://blog.csdn.net/zsj2016o/article/details/111285518 作者:zsj ,转载请注明.

好久没有写文章,这段时间一直在着急赶项目,时间一直被压缩,手里积累了不少想分享的资源,现在开始陆陆续续的编写,希望大家都在自己的技术之路上,越走越远,越研越深。

#此次分享的是 利用STM32解析GPS(北斗)数据,利用STM32F103串口接收SKG12D发来的定位数据,并进行接收判断,有效性判断以及关键信息提取。

1、GPS(北斗)介绍
这部分我就不多说了,相信你在查找资料的过程中,已经了解的7788,这部分不是你想看的,甚至是已经看吐了,这里一笔带过(原
谅我的懒,不愿意去百度复制粘贴)。

2、模组介绍
我采用的天工家的SKG12D,为什么这么选我也就不多说了,直接上Datasheet。
https://download.csdn.net/download/zsj2016o/13704204,这里面包含三个,分别是SKG12A、SKG12B、SKG12D,我用的是SKG12D的模组。

3、解析说明
大家通常使用GPS或者北斗获取当前的定位信息、时间信息,如果只需要这些,处理GPS或北斗发来的数据只需要解析RMC(可能是GPRMC或者是GNRMC)数据包即可。
下图为SKG12D手册中关于RMC的表述
在这里插入图片描述
我后面给出的程序里,只写了关于RMC的解析,程序是自己写的,不喜勿喷。
驱动中包括三部分,数据包接收判定(串口有数据并且一定时间内无变化)、数据包校验(根据协议格式判断)、数据解析(提取关键信息,时间及位置)。

void BeidouMain(void)
{ 
	
	Beidou_RecPackCheck();//wifi接收检测,是否有数据RecPackOk =1	
	
	BeiDouDataReceivePro();  //wifi数据检测,是否有RMC数据包
	
	BeiDouDataPrasePro();		 //wifi数据解析

}

/*
函数说明:
				此函数用来检测是否接收到RMC数据包,根据RMC协议格式进行解析,
				本方式是根据协议格式,具体说是定位成功的协议格式进行判断,
				成功 BeiDouRecType = RMC BeiDou.location定位标志 为'A'
				不成功,有两种情况,一个是不为RMC包,如果为RMC包,那就定位
				不成功,BeiDou.location = 'V'
				
				
*/
#define BeiDouRecPrintor 67
void BeiDouDataReceivePro(void)
{
	u16 i,j;	
	u8 sun = 0;
	u8 sumH = 0;
	u8 sumL = 0;

	if(BeiDouUart.RecPackOk != 1 ) return;//接收到数据再往下进行
	
	for(i = 0;i<255;i++)
	{
		if(BeiDouUart.RxBuf[i] == '$')
		{
			if(BeiDouUart.RxBuf[i+BeiDouRecPrintor] == '*')
			{
				for(j = 1;j<BeiDouRecPrintor;j++)
				{
						sun ^= BeiDouUart.RxBuf[i+j];
				}
				if((BeiDouUart.RxBuf[i+BeiDouRecPrintor+1] <0x3a) && (BeiDouUart.RxBuf[i+BeiDouRecPrintor+1]  > 0x2f))//
				{
						sumH = BeiDouUart.RxBuf[i+BeiDouRecPrintor+1]-0x30;//校验和高位
				}
				else if((BeiDouUart.RxBuf[i+BeiDouRecPrintor+1] <0x47) && (BeiDouUart.RxBuf[i+BeiDouRecPrintor+1]  > 0x40))//
				{
						sumH = BeiDouUart.RxBuf[i+BeiDouRecPrintor+1]-0x37;//校验和高位
				}
				 
				if((BeiDouUart.RxBuf[i+BeiDouRecPrintor+2] <0x3a) && (BeiDouUart.RxBuf[i+BeiDouRecPrintor+2]  > 0x2f))//
				{
						sumL = BeiDouUart.RxBuf[i+BeiDouRecPrintor+2]-0x30;//校验和高位
				}
				else if((BeiDouUart.RxBuf[i+BeiDouRecPrintor+2] <0x47) && (BeiDouUart.RxBuf[i+BeiDouRecPrintor+2]  > 0x40))//
				{
						sumL = BeiDouUart.RxBuf[i+BeiDouRecPrintor+2]-0x37;//校验和高位
				}
				 if(sun == ((sumH&0x0f)<<4)+(sumL&0x0f))//完成数据校验,成功接收
				 {			 
						 BeiDouRecType = RMC;        //校时数据包(0x02)
						 BeiDouUart.RxCheckPoint	= i; //记录数据位置
				 }
				 else
				 {
						 BeiDou.location = 'V';
				 }
			}
			else
			{
				if((BeiDouUart.RxBuf[i+3] == 'R')&&(BeiDouUart.RxBuf[i+4] == 'M')&&(BeiDouUart.RxBuf[i+5] == 'C'))
				{
						 BeiDou.location = 'V';
						 BeiDouCleanBuf();
						 BeiDouUart.RxPrinter = 0;	
						 BeiDouUart.RecPackOk = 0;
						 BeiDouUart.RxCheckPoint = 0;
				}			
			}
			
		}
		else
		{
			if((i == 254)&&(BeiDouRecType == 0))
			{
				BeiDouCleanBuf();
			  BeiDouUart.RxPrinter = 0;	
			  BeiDouUart.RecPackOk = 0;
			  BeiDouUart.RxCheckPoint = 0;
			}
			else
			{
				;
			}
		}
	}
	
}
/*
函数说明:
				本函数为成功接收一个包RMC数据后,对其进行解析,具体内容见协议,其中重要的数据是定位状态,
				北斗数据只有在定位成功后,才是真实有效的,再用数据之前,首先要确定定位成功,当前的机制只
				会接受成功数据,因此都是定位成功的,程序添加了一个逻辑判断,30秒之内 不重复解析(30内只解析一次)
*/
void BeiDouDataPrasePro(void)
{
	u8 i;
	u8 time;
	u8 lon,lat;
	u16 lon_l,lat_l;
	if(BeiDouRecType == 0 ) return;//接收到数据再往下进行
	
	if(BeiDou_RecTimer_1ms != 0) 
	{
		BeiDouRecType = 0;
		BeiDouUart.RecPackOk = 0;
		BeiDouCleanBuf();
		BeiDouUart.RxPrinter=0;	
		BeiDouUart.RecPackOk = 0;
		BeiDouUart.RxCheckPoint = 0;
		return;
	}
	switch( BeiDouRecType )
	{
		case RMC:
						BeiDou_RecTimer_1ms = 30*1000;//每30s 对数据进行处理一次
						time = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+64]&0x0f)*10)+		  (BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+65]&0x0f);
						BeiDou.year= time;//年
		
						time = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+62]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+63]&0x0f);
						BeiDou.month = time;//月
						
						time = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+60]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+61]&0x0f);
						BeiDou.date = time;//日
		
						time = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+7]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+8]&0x0f);
						BeiDou.hour = time;//时
						
						time = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+9]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+10]&0x0f);
						BeiDou.minute = time;//分
						
						time = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+11]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+12]&0x0f);
						BeiDou.second= time;//秒
		
						BeiDou.location = BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+18]; //定位状态
						
						lon =  ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+33]&0x0f)*100)+((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+34]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+35]&0x0f);
						BeiDou.lon_h = lon; //经度,度
						lon = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+36]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+37]&0x0f);
						BeiDou.lon_m = lon; //经度,0.01度
						lon_l = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+39]&0x0f)*10000)+((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+40]&0x0f)*1000)+((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+41]&0x0f)*100)+
											 ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+42]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+43]&0x0f);
						BeiDou.lon_l = lon_l; //经度,0.00001度
						
						lat = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+20]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+21]&0x0f);
						BeiDou.lat_h =  lat; //经度,度
						lat = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+22]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+23]&0x0f);
						BeiDou.lat_m = lat; //经度,0.01度
						lat_l = ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+25]&0x0f)*10000)+((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+26]&0x0f)*1000)+((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+27]&0x0f)*100)+
											 ((BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+28]&0x0f)*10)+(BeiDouUart.RxBuf[BeiDouUart.RxCheckPoint+29]&0x0f);
						BeiDou.lat_l = lat_l; //经度,0.00001度
						
						BeiDouUart.RecPackOk  = No;
						BeiDouRecType = 0;
						BeiDouCleanBuf();
					  BeiDouUart.RxPrinter=0;	
					  BeiDouUart.RecPackOk = 0;
					  BeiDouUart.RxCheckPoint = 0;
						
						break;
		
		default:
			break;
	}
}

自己写的一个粗糙的北斗数据接收的驱动程序,利用正点原子的串口驱动,外加北斗模块的驱动程序组合而来,简单修改,即可使用。
https://download.csdn.net/download/zsj2016o/13704229
本人属于菜还爱玩类型,水平一般但是喜欢写,不喜勿喷!

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页