stm32+neo6m GPS模块定位系统 您所在的位置:网站首页 GPS授时模块工作原理 stm32+neo6m GPS模块定位系统

stm32+neo6m GPS模块定位系统

2024-06-11 23:25| 来源: 网络整理| 查看: 265

开发平台:主处理器是意法半导体的stm32f103系列,这款芯片应用广泛,并且资料很多。

主要定位模块:ublox的一款芯片

开发环境:MDK5.0

主要代码还是参考原子的历程,在它的基础上实现了只提取经纬度,海拔等操作

硬件连接:3.3V电源给GPS模块供电,stm32串口2接GPS。

软件实现主要流程:stm32串口初始化,模块初始化,设置更新速率,保存配置,串口2接收消息,对接收到的消息进行字符串处理,提取有用的信息加以利用。

以下给出主要程序:

串口部分:

串口2初始化代码:

void USART2_Init_JAVE( u32 bound ) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; USART_DeInit(USART2); //使能串口3的时钟 和对应GPIO时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //配置TX引脚GPIO GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStructure); //配置RX引脚GPIO GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); //配置串口2 USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); //使能串口2 USART_Cmd(USART2,ENABLE); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //配置串口2接收中断 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ClearFlag(USART2, USART_FLAG_RXNE); USART_GetFlagStatus(USART2,USART_FLAG_TC); /* 先读SR,再写DR */ }

串口2中断函数:

void RX2_Handler( void ) { char temp = 0; #ifdef OS_TICKS_PER_SEC //如果时钟节拍数定义了,说明要使用ucosII了. OSIntEnter(); #endif if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET) { temp = USART_ReceiveData( USART2 ); /* 读取USART2数据,自动清零标志位 RXNE */ if( RX2_Point id=0X0806; //cfg rate id cfg_rate->dlength=6; //数据区长度为6个字节. cfg_rate->measrate=measrate;//脉冲间隔,ms cfg_rate->navrate=1; //导航速率(周期),固定为1 cfg_rate->timeref=reftime; //参考时间为GPS时间 Ublox_CheckSum((unsigned char*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb); // while(DMA1_Channel7->CNDTR!=0); //等待通道7传输完成 // UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_rate));//通过dma发送出去 Ublox_Send_Date((unsigned char*)cfg_rate,sizeof(_ublox_cfg_rate));//发送数据给NEO-6M return Ublox_Cfg_Ack_Check(); }

GPS初始化:

unsigned char GPS_Init(void) { unsigned char key = 0xFF,cnt=0; //保存配置成功的标志,成功时返回的值是0; MyPrintf("GPS 初始化\r\n"); Ublox_Cfg_Prt(38400); //重新设置模块的波特率为38400 while((Ublox_Cfg_Rate(2000,1)!=0)&&key) //持续判断,直到可以检查到NEO-6M,且数据保存成功 { MyPrintf("2"); USART2_Init_JAVE( 38400 ); //初始化串口2波特率为9600(EEPROM没有保存数据的时候,波特率为9600.) Ublox_Cfg_Prt(38400); //重新设置模块的波特率为38400 if(++cnt>=5) return 1; //错误 key=Ublox_Cfg_Cfg_Save(); //保存配置,配置成功,返回0 delay_ms(50); } return 0; }

算法处理部分:(字符串处理)

对于接收到的消息进行提取处理:

//分析GPGGA信息 //gpsx:nmea信息结构体 //buf:接收到的GPS数据缓冲区首地址 void NMEA_GPGGA_Analysis(GPS_PacketTypeDef *GPS_Packet,u8 *buf) { unsigned char *p1,dx,posx; unsigned int temp; float rs; p1=(unsigned char *)strstr((const char *)buf,"$GPGGA"); //此处可改为"$GPGGA" posx=NMEA_Comma_Pos(p1,9); //得到海拔高度 if(posx!=0XFF){ GPS_Packet->altitude=NMEA_Str2num(p1+posx,&dx); MyPrintf("altitude=%d\r\n",GPS_Packet->altitude); } posx=NMEA_Comma_Pos(p1,2); //得到纬度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); GPS_Packet->latitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' GPS_Packet->latitude=GPS_Packet->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° MyPrintf("latitude=%d\r\n",GPS_Packet->latitude); } posx=NMEA_Comma_Pos(p1,4); //得到经度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); GPS_Packet->longitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' GPS_Packet->longitude=GPS_Packet->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° MyPrintf("longitude=%d\r\n",GPS_Packet->longitude); } posx=NMEA_Comma_Pos(p1,6); //定位状态 if(posx!=0XFF){ GPS_Packet->status=*(p1+posx)-'0'; MyPrintf("status=%d\r\n",GPS_Packet->status); } }

GPS测试主程序:

unsigned char GPS_Run(void) { unsigned char flag=0; //定位信息成功标志 unsigned short rxlen,i; //rxlen:数据长度 unsigned char cnt=0; while(1) { if(cnt>2) {sign_run=1;return 0;} cnt++; rxlen=0; USART2_Scan(&rxlen); if(rxlen !=0) { for(i=0;ireserved=0; //保留字节,设置为0 cfg_prt->txready=0; //TX Ready设置为0 cfg_prt->mode=0X08D0; //8位,1个停止位,无校验位 cfg_prt->baudrate=baudrate; //波特率设置 cfg_prt->inprotomask=0X0007;//0+1+2 cfg_prt->outprotomask=0X0007;//0+1+2 cfg_prt->reserved4=0; //保留字节,设置为0 cfg_prt->reserved5=0; //保留字节,设置为0 Ublox_CheckSum((unsigned char*)(&cfg_prt->id),sizeof(_ublox_cfg_prt)-4,&cfg_prt->cka,&cfg_prt->ckb); // while(DMA1_Channel7->CNDTR!=0); //等待通道7传输完成 // UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_prt)); //通过dma发送出去 Ublox_Send_Date((unsigned char*)cfg_prt,sizeof(_ublox_cfg_prt));//发送数据给NEO-6M delay_ms(200); //等待发送完成 USART2_Init_JAVE(baudrate); //重新初始化串口2 return Ublox_Cfg_Ack_Check();//这里不会反回0,因为UBLOX发回来的应答在串口重新初始化的时候已经被丢弃了. } //配置保存 //将当前配置保存在外部EEPROM里面 //返回值:0,执行成功;1,执行失败. unsigned char Ublox_Cfg_Cfg_Save(void) { unsigned char i; _ublox_cfg_cfg *cfg_cfg=(_ublox_cfg_cfg *)USART2_TX_BUF; cfg_cfg->header=0X62B5; //cfg header cfg_cfg->id=0X0906; //cfg cfg id cfg_cfg->dlength=13; //数据区长度为13个字节. cfg_cfg->clearmask=0; //清除掩码为0 cfg_cfg->savemask=0XFFFF; //保存掩码为0XFFFF cfg_cfg->loadmask=0; //加载掩码为0 cfg_cfg->devicemask=4; //保存在EEPROM里面 Ublox_CheckSum((unsigned char*)(&cfg_cfg->id),sizeof(_ublox_cfg_cfg)-4,&cfg_cfg->cka,&cfg_cfg->ckb); // while(DMA1_Channel7->CNDTR!=0); //等待通道7传输完成 // UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_cfg)); //通过dma发送出去 Ublox_Send_Date((unsigned char*)cfg_cfg,sizeof(_ublox_cfg_cfg));//发送数据给NEO-6M for(i=0;iid=0X0806; //cfg rate id cfg_rate->dlength=6; //数据区长度为6个字节. cfg_rate->measrate=measrate;//脉冲间隔,ms cfg_rate->navrate=1; //导航速率(周期),固定为1 cfg_rate->timeref=reftime; //参考时间为GPS时间 Ublox_CheckSum((unsigned char*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb); // while(DMA1_Channel7->CNDTR!=0); //等待通道7传输完成 // UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_rate));//通过dma发送出去 Ublox_Send_Date((unsigned char*)cfg_rate,sizeof(_ublox_cfg_rate));//发送数据给NEO-6M return Ublox_Cfg_Ack_Check(); } //从buf里面得到第cx个逗号所在的位置 //返回值:0~0XFE,代表逗号所在位置的偏移. // 0XFF,代表不存在第cx个逗号 unsigned char NMEA_Comma_Pos(unsigned char *buf,unsigned char cx) { unsigned char *p=buf; while(cx) { if(*buf=='*'||*buf'z')return 0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号 if(*buf==',')cx--; buf++; } return buf-p; } //m^n函数 //返回值:m^n次方. unsigned int NMEA_Pow(unsigned char m,unsigned char n) { unsigned int result=1; while(n--) result*=m; return result; } //str转换为数字,以','或者'*'结束 //buf:数字存储区 //dx:小数点位数,返回给调用函数 //返回值:转换后的数值 int NMEA_Str2num(unsigned char *buf,unsigned char*dx) { unsigned char *p=buf; unsigned int ires=0,fres=0; unsigned char ilen=0,flen=0,i; unsigned char mask=0; int res; while(1) //得到整数和小数的长度 { if(*p=='-'){mask|=0X02;p++;}//是负数 if(*p==','||(*p=='*'))break;//遇到结束了 if(*p=='.'){mask|=0X01;p++;}//遇到小数点了 else if(*p>'9'||(*paltitude); } posx=NMEA_Comma_Pos(p1,2); //得到纬度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); GPS_Packet->latitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' GPS_Packet->latitude=GPS_Packet->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° MyPrintf("latitude=%d\r\n",GPS_Packet->latitude); } posx=NMEA_Comma_Pos(p1,4); //得到经度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); GPS_Packet->longitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' GPS_Packet->longitude=GPS_Packet->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° MyPrintf("longitude=%d\r\n",GPS_Packet->longitude); } posx=NMEA_Comma_Pos(p1,6); //定位状态 if(posx!=0XFF){ GPS_Packet->status=*(p1+posx)-'0'; MyPrintf("status=%d\r\n",GPS_Packet->status); } } void Ublox_Send_Date(unsigned char* dbuf,unsigned short len) { unsigned short j; for(j=0;jSR&0X40)==0);//循环发送,直到发送完毕 USART2->DR=dbuf[j]; } } u8 GPS_Check(u8 *buff) { u8 *p_start,*p_process; //,*p_end; // u8 temp[500]; u8 res=0; // u16 cnt=0,i=0; // MyPrintf("检查GPS数据\r\n"); p_start =(u8*)strstr((const char*)buff,"$GPRMC"); if(p_start!=NULL) //找不到地理位置信息,返回无效 { if(strstr((const char*)p_start,"$GPVTG")!=NULL && strstr((const char*)p_start,"$GPGGA")!=NULL) if(strstr((const char*)p_start,"$GPGSA")!=NULL && strstr((const char*)p_start,"$GPGSV")!=NULL) if((p_process=(u8*)strstr((const char*)p_start,"$GPGLL"))!=NULL) { // MyPrintf("检查无效字符\r\n"); if((strstr((const char*)p_process,"V"))!=NULL) res=0xFF; } }else res=1; // MyPrintf("GPS Check Result=%d\r\n",res); return res; //返回无效定位数据 }

H文件:

#ifndef _NEO_6M_ #define _NEO_6M_ #include "global.h" //UBLOX NEO-6M 配置(清除,保存,加载等)结构体 __packed typedef struct { unsigned short header; //cfg header,固定为0X62B5(小端模式) unsigned short id; //CFG CFG ID:0X0906 (小端模式) unsigned short dlength; //数据长度 12/13 unsigned int clearmask; //子区域清除掩码(1有效) unsigned int savemask; //子区域保存掩码 unsigned int loadmask; //子区域加载掩码 unsigned char devicemask; //目标器件选择掩码 b0:BK RAM;b1:FLASH;b2,EEPROM;b4,SPI FLASH unsigned char cka; //校验CK_A unsigned char ckb; //校验CK_B }_ublox_cfg_cfg; //UBLOX NEO-6M UART端口设置结构体 __packed typedef struct { unsigned short header; //cfg header,固定为0X62B5(小端模式) unsigned short id; //CFG PRT ID:0X0006 (小端模式) unsigned short dlength; //数据长度 20 unsigned char portid; //端口号,0=IIC;1=UART1;2=UART2;3=USB;4=SPI; unsigned char reserved; //保留,设置为0 unsigned short txready; //TX Ready引脚设置,默认为0 unsigned int mode; //串口工作模式设置,奇偶校验,停止位,字节长度等的设置. unsigned int baudrate; //波特率设置 unsigned short inprotomask; //输入协议激活屏蔽位 默认设置为0X07 0X00即可. unsigned short outprotomask; //输出协议激活屏蔽位 默认设置为0X07 0X00即可. unsigned short reserved4; //保留,设置为0 unsigned short reserved5; //保留,设置为0 unsigned char cka; //校验CK_A unsigned char ckb; //校验CK_B }_ublox_cfg_prt; //UBLOX NEO-6M 刷新速率配置结构体 __packed typedef struct { unsigned short header; //cfg header,固定为0X62B5(小端模式) unsigned short id; //CFG RATE ID:0X0806 (小端模式) unsigned short dlength; //数据长度 unsigned short measrate; //测量时间间隔,单位为ms,最少不能小于200ms(5Hz) unsigned short navrate; //导航速率(周期),固定为1 unsigned short timeref; //参考时间:0=UTC Time;1=GPS Time; unsigned char cka; //校验CK_A unsigned char ckb; //校验CK_B }_ublox_cfg_rate; unsigned char Ublox_Cfg_Prt(unsigned int baudrate); unsigned char Ublox_Cfg_Cfg_Save(void); void Ublox_Send_Date(unsigned char* dbuf,unsigned short len); void NMEA_GPGGA_Analysis(GPS_PacketTypeDef *GPS_Packet,unsigned char *buf); unsigned char Ublox_Cfg_Rate(unsigned short measrate,unsigned char reftime); u8 GPS_Check(u8 *buff); #endif



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有