STM32传感器模块编程实践(十九) 光子物联北斗GPS定位模块简介及驱动源码

文章目录

一.概要

光子物联北斗GPS模块是基于中科微AT6558芯片的一款GPS定位模块,具有高灵敏度、低功耗、小型化高追踪灵敏度,大大扩大了其定位的覆盖面,在普通GPS接收模块不能定位的地方,如狭窄都市天空下、密集的丛林环境,光子物联北斗GPS模块只要在有北斗或者GPS信号的空旷空间,都能高精度定位。模块的高灵敏度、小静态漂移、低功耗及轻巧的体积,适用于车载、手持设备如PDA,车辆监控、手机、摄像机及其他移动定位系统的应用,是GPS定位产品应用的好选择。

二.光子物联北斗GPS模块主要技术指标

1.模块采用中科微AT6558芯片模组,体积小巧,性能优异。

2.支持多种卫星导航系统,包括中国的 BDS(北斗卫星导航系统),美国的 GPS。

3.模块增加放大电路,有利于快速搜星,可以安装GPS外置天线比如陶瓷天线或者北斗GPS二合一天线。

4.模块可通过串口进行各种参数设置,并可保存在EEPROM,使用方便。

5.模块自带SMA接口,可以连接各种有源天线,适应能力强。

6.模块兼容3.3V/5V电平,方便连接各种单片机系统。

7.模块自带可充电后备电池,可以掉电保持星历数据。

7.跟踪灵敏度 --162dBm ,冷启动灵敏度--148 dBm。(跟踪灵敏度是GPS接收机在捕获到卫星信号之后,能够导航的最低信号强度;冷启动灵敏度是设备从完全没有信号状态到成功捕获到至少一颗卫星信号所需的最低信号强度)

8.冷启动时间40秒。

9.定位精度:<3m。

10.工作温度范围:--40° C 至 85° C。

11.模块尺寸25mm*35mm。

12.安装孔径3mm。

三.北斗GPS模块参考原理图

光子物联北斗GPS模块参考原理图如下,模块引出了TX,RX,GND,VCC引脚。

四.光子物联北斗GPS模块接线说明

模块如图所示:

模块插针信号定义:

北斗GPS模块与单片机只要4根线就能连接

单片机开发板 北斗GPS模块

3.3V-----------------------VCC

GND----------------------GND

PA2-----------------------RX

PA3-----------------------TX

五.北斗GPS模块通讯协议介绍(NMEA-0183)

串口通讯参数:9600波特率,8位数据,1位停止位,无校验。

北斗GPS模块通过串口输出北斗与GPS融合的定位数据信息,这些信息默认采用NMEA-0183协议,协议简介如下:

NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备

制定的标准格式。目前业已成了GPS导航设备统一的RTCM(Radio Technical Commission for

Maritime services)标准协议。

NMEA-0183协议采用ASCII码来传递GPS定位信息,我们称之为帧。

帧格式形如: a a c c c , d d d , d d d , ... , d d d ∗ h h ( C R ) ( L F ) 1 、" aaccc,ddd,ddd,...,ddd*hh(CR)(LF) 1、" aaccc,ddd,ddd,...,ddd∗hh(CR)(LF)1、"":帧命令起始位

2、aaccc:地址域,前两位为识别符(aa),后三位为语句名(ccc)

3、ddd...ddd:数据

4、"":校验和前缀(也可以作为语句数据结束的标志)
5、hh:校验和(check sum),$与
之间所有字符ASCII码的校验和(各字节做异或运算,得到

校验和后,再转换16进制格式的ASCII字符)

6、(CR)(LF):帧结束,回车和换行符

UTC 时间即协调世界时,相当于本初子午线(0度经线)上的时间,北京时间比UTC早8个小时。

我们以常用的经纬度数据读取为例
GNRMC - 推荐最小定位信息
格式示例 :$GNRMC,121937.000,A,3015.03468,N,11955.87521,E,1.06,0.00,060326,A,V*0D
关键字段(按顺序逗号分隔)

UTC时间:121937.000

定位状态:A -> 有效定位;V -> 无效警告

纬度:3015.03468

纬度半球:N -> 北纬

经度:11955.87521

经度半球:E -> 东经

地面速率:1.06节

地面航向:0.00度

UTC日期:060326

模式指示(新版本):A=自主定位,D=差分,E=估算,N=无效

协议解析代码:

c 复制代码
//计算GNRMC的校验和,返回1说明校验成功
uint16_t NMEA_GPRMC_CheckSum(uint8_t *buf)
{
	uint8_t i,j,ch1,ch2;
	uint16_t CheckSum=0;
	uint16_t CheckData;
  for(i=0;i<120;i++)
	{
		if(*(buf+i)=='*')//查找校验结束符,从而确定需要计算校验的区间
		{
			break;
		}
	}
	for(j=0;j<i;j++)//从GPRMC第一个字符开始,到*的前一个字符结束,计算异或校验
	{
		CheckSum^=*(buf+j);//异或校验
	}
	ch1=*(buf+i+1);//获取协议中的校验码
	ch2=*(buf+i+2);
 CheckData = (ch1 >= '0' && ch1 <= '9') ? (ch1 - '0') : (ch1 - 'A' + 10);
 CheckData = (CheckData << 4) | ((ch2 >= '0' && ch2 <= '9') ? (ch2 - '0') : (ch2 - 'A' + 10));
	if(CheckSum==CheckData)//两个校验值比较,如果相等,说明数据有效
	{
		return 1;
	}
	return 0;
}

//分析GNRMC信息
//gpsx:nmea信息结构体
//buf:接收到的北斗GPS数据缓冲区首地址
//$GNRMC,121937.000,A,3015.03468,N,11955.87521,E,1.06,0.00,060326,,,A,V*0D
//数据解析:121937.000:UTC时间,A:数据有效,3015.03468:纬度,N:北纬,11955.87521:经度,E:东经,1.06:航速节,0.00:航向,060326:日期,A:自主定位,
void NMEA_GNRMC_Analysis(nmea_msg *gpsx,uint8_t *buf)
{
	uint8_t *p1,dx;			 
	uint8_t posx;     
	uint32_t temp;	   
	float rs;  
	
	p1=(uint8_t*)strstr((const char *)buf,"GNRMC");//"$GNRMC",经常有&和GNRMC分开的情况,故只判断GNRMC.
	if(NMEA_GPRMC_CheckSum(p1)==0)//校验不通过,不进行解析,显示
	{
		return;
	}
	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;//转换为° 
	}
	posx=NMEA_Comma_Pos(p1,4);								//南纬还是北纬 
	if(posx!=0XFF)gpsx->nshemi=*(p1+posx);					 
 	posx=NMEA_Comma_Pos(p1,5);								//得到经度
	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;//转换为° 
	}
	posx=NMEA_Comma_Pos(p1,6);								//东经还是西经
	if(posx!=0XFF)gpsx->ewhemi=*(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;	 	 
	} 
}

六.北斗GPS模块操作流程

连接北斗GPS模块‌:使用USB-TTL工具或者单片机与北斗GPS模块连接,确保VCC和GND引脚正确对接,TXD和RXD引脚也需要正确连接。

‌配置北斗GPS模块‌:通过编程设置北斗GPS模块的工作模式,例如每秒自动输出一次经纬度、海拔和UTC时间。

‌读取数据‌:编写程序读取北斗GPS模块输出的NMEA-0183协议数据。程序需要解析这些数据,提取出经纬度、海拔高度和UTC时间等信息‌。

‌数据处理与展示‌:将解析出的数据通过串口调试终端或通过OLED显示屏显示经纬度、海拔和UTC时间等信息‌。

‌注意事项‌:

北斗GPS模块上电后需要1~3分钟进行搜星定位,具体时间取决于信号强度和环境‌,比如雨雪天气或者天上云层较厚的情况时间下会长一些。

北斗GPS模块天线需要放在室外露天无遮挡环境,在信号较弱的环境中,可能需要更换有源天线以提高定位速度和准确性‌。

确保编程时正确使用NMEA-0183协议的帧格式,正确解析数据‌。

七.STM32单片机与北斗GPS模块通讯实验

1.硬件准备

STLINK接STM32F103C8T6开发板,STLINK接电脑USB口。

北斗GPS模块与单片机开发板接线:

复制代码
开发板3.3V         <->模块VCC
开发板PA2脚        <->模块RX
开发板PA3脚        <->模块TX
开发板GND          <->模块GND 

2.软件工程

打开STM32CubeMX软件,新建工程

Part Number处输入STM32F103C8,再双击就创建新的工程

配置下载口引脚

配置外部晶振引脚

配置系统主频

配置串口2,9600波特率,8位数据,1位停止位,无校验

串口2中断使能

配置工程文件名,保存路径,KEIL5工程输出方式

生成工程

用Keil5打开工程

添加代码

main函数里添加串口接收中断,模块波特率配置,GPS数据配置。

串口2接收中断处理。

北斗GPS经纬度,时间数据接收解析。

北斗GPS速度,海拔数据接收解析。

3.软件主要代码

串口数据接收相关代码

c 复制代码
//串口接收缓存区 	
uint8_t USART2_RX_BUF[USART_MAX_RECV_LEN]; 				    //接收缓冲,最大USART_MAX_RECV_LEN个字节.
volatile uint8_t UartRxData;
uint8_t UartTxbuf[1000]={1,2,3,4,5,6,7,8,9,10};
uint8_t UartRxbuf[1024],UartIntRxbuf[1024];
uint16_t UartRxIndex=0,UartRxFlag,UartRxLen=0,UartRxTimer,UartRxOKFlag,UartIntRxLen;

//串口清除
uint8_t UartRecv_Clear(void)
{
	UartRxOKFlag=0;
	UartRxLen=0;
	UartIntRxLen=0;
	UartRxIndex=0;
	return 1;
}

//接收标志函数,返回0说明没收据接收,返回1说明有数据收到
uint8_t Uart_RecvFlag(void)
{
		if(UartRxOKFlag==0x55)
		{
			UartRxOKFlag=0;
			UartRxLen=UartIntRxLen;
			memcpy(USART2_RX_BUF,UartIntRxbuf,UartIntRxLen);//把缓冲区的数据,放入需要解析的数组
			UartIntRxLen=0;
			return 1;
		}
		return 0;
}
//串口2在1字节接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	if(huart==&huart2)//判断是否串口2
	{
		UartRxFlag=0x55;//接收标志置位
		UartIntRxbuf[UartRxIndex]=UartRxData;//数据写入缓冲区
		UartRxIndex++;//记载数目加1
		if(UartRxIndex>=1024)//缓冲区是1024字节,如果存满,归零
		{
			UartRxIndex=0;
		}
		HAL_UART_Receive_IT(&huart2,(unsigned char*)&UartRxData,1);//继续接收下一字节
 }

}

//1ms调用一次,用来判断是否收完一帧
void UART_RecvDealwith(void)
{
	if(UartRxFlag==0x55)
	{
		if(UartIntRxLen<UartRxIndex)//UartIntRxLen小于UartRxIndex,说明有收到新的数据,把接收长度增加
		{
		UartIntRxLen=UartRxIndex;
		}else
		{
			UartRxTimer++;
			if(UartRxTimer>=50)//50ms,等待,没收到新数据,说明已经收完一帧
			{
				UartRxTimer=0;
				UartRxFlag=0;
				UartRxOKFlag=0x55;
				UartRxIndex=0;
			}
		}
	}
}
  

main函数代码

c 复制代码
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();//1ms systick配置
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();//8M外部晶振,72M系统主频

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init(); //串口2初始化,波特率9600,PA2:USART2_TX,PA3:USART2_RX
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&UartRxData, 1);//接收中断使能
	OLED_Init();//OLED初始化  
	OLED_Clear();//清屏
	HAL_Delay(100);//等待100ms
	Bds_Cfg_Prt(9600);//模块出厂默认是9600波特率,此处设置北斗模块波特率为9600,如果是其他波特率,设置完之后,需要初始化单片机的波特率,与模块的波特率对应
	HAL_Delay(100);//等待100ms
	Bds_Cfg_Rate(1000);//设置北斗模块定位信息更新速度为1000ms 
	HAL_Delay(100);//等待100ms
	Bds_Cfg_Msg();//配置读取的内容,GGA(GPS定位数据),RMC(推荐最小定位信息),VTG(地面速度信息)
	HAL_Delay(100);//等待100ms
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		OLED_Clear();//清屏
		OLED_ShowCHinese(18,0,0);//光
		OLED_ShowCHinese(36,0,1);//子
		OLED_ShowCHinese(54,0,2);//物
		OLED_ShowCHinese(72,0,3);//联
		OLED_ShowCHinese(90,0,4);//网
		BdsDataRead();//读取经纬度,时间信息,并在液晶上显示,模块的LED灯闪烁,说明模块经纬度已经读取到
		HAL_Delay(800);//等待800ms
  }
  /* USER CODE END 3 */
}

GPS数据解析相关

c 复制代码
//分析GNRMC信息
//gpsx:nmea信息结构体
//buf:接收到的北斗GPS数据缓冲区首地址
//$GNRMC,121937.000,A,3015.03468,N,11955.87521,E,1.06,0.00,060326,,,A,V*0D
//数据解析:121937.000:UTC时间,A:数据有效,3015.03468:纬度,N:北纬,11955.87521:经度,E:东经,1.06:航速节,0.00:航向,060326:日期,A:自主定位,
void NMEA_GNRMC_Analysis(nmea_msg *gpsx,uint8_t *buf)
{
	uint8_t *p1,dx;			 
	uint8_t posx;     
	uint32_t temp;	   
	float rs;  
	
	p1=(uint8_t*)strstr((const char *)buf,"GNRMC");//"$GNRMC",经常有&和GNRMC分开的情况,故只判断GNRMC.
	if(NMEA_GPRMC_CheckSum(p1)==0)//校验不通过,不进行解析,显示
	{
		return;
	}
	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;//转换为° 
	}
	posx=NMEA_Comma_Pos(p1,4);								//南纬还是北纬 
	if(posx!=0XFF)gpsx->nshemi=*(p1+posx);					 
 	posx=NMEA_Comma_Pos(p1,5);								//得到经度
	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;//转换为° 
	}
	posx=NMEA_Comma_Pos(p1,6);								//东经还是西经
	if(posx!=0XFF)gpsx->ewhemi=*(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;	 	 
	} 
}

4.实验效果

显示经度,纬度以及时间,时间会走秒。

八.视频演示效果及操作说明

光子物联北斗GPS模块连接

九.小结

北斗GPS模块,同时接收 GPS、北斗(BDS)信号,是一种用于定位、导航和追踪的电子设备。在复杂环境下也能提供更稳定、更可靠的定位服务,解决了单GPS在信号遮挡处易丢星的问题。这类模块广泛应用于个人定位、汽车导航、轨迹追踪、便携设备等领域,学好了北斗GPS模块,能应用到更多的嵌入式开发中。

相关推荐
可乐鸡翅好好吃2 小时前
协议栈烧录问题
单片机·嵌入式硬件
仰泳之鹅3 小时前
【51单片机】第一课:单片机简介与软件安装
单片机·嵌入式硬件·51单片机·1024程序员节
2201_756206343 小时前
STM32F407 + ML307 阿里云物联网项目总结
c语言·开发语言·嵌入式硬件
Zarek枫煜3 小时前
[特殊字符]栈(Stack)原理详解 \+ Zig / C3 双语言实现
c语言·单片机·嵌入式硬件·算法
小草cys3 小时前
轮足机器人无法直立的原因,哎
单片机·嵌入式硬件·机器人
kyle~3 小时前
ROS2 Control
c++·嵌入式硬件·机器人·ros2
EVERSPIN3 小时前
单片机外扩SRAM芯片:Async Fast EMI504WF08VB-10IE应用
单片机·嵌入式硬件·sram芯片·外扩sram·外扩sram芯片
LCG元3 小时前
STM32嵌入式开发:基于STM32F103的智能水族箱控制
stm32·单片机·嵌入式硬件
凌盛羽4 小时前
使用python绘图分析电池充电曲线
开发语言·python·stm32·单片机·fpga开发·51单片机