AN1303ATK-NEO-6MGPS模块使用本应用文档(AN1302,对应战舰STM32开发板扩展实验3/MiniSTM32开发板扩展实验23)将教大家如何在ALIENTEKSTM32开发板上使用ATK-NEO-6MGPS模块(注意,本文档同时适用ALIENTEK战舰和MiniSTM32两款开发板),并实现GPS定位。本文档分为如下几部分:1,ATK-NEO-6MGPS模块简介2,硬件连接3,软件实现4,验证1、ATK-NEO-6MGPS模块简介ATK-NEO-6M模块,是ALIENTEK生成的一款高性能GPS模块,模块核心采用UBLOX公司的NEO-6M模组,具有50个通道,追踪灵敏度高达-161dBm,测量输出频率最高可达5Hz。ATK-NEO-6M模块自带高性能无源陶瓷天线(无需再购买昂贵的有源天线了),兼容3.3V和5V单片机系统,并自带可充电后备电池(支持温启动或热启动)。ATK-NEO-6M模块非常小巧(25.5mm*31mm),模块通过4个2.54mm间距的排针与外部连接,模块外观如图1.1所示:图1.1ATK-NEO-6M模块外观图图1.1中,从右到左,依次为模块引出的PIN1~PIN4脚,各引脚的详细描述如表1.1所示:序号名称说明1RXD模块串口接收脚(TTL电平,不能直接接RS232电平!),可接单片机的TXD2TXD模块串口发送脚(TTL电平,不能直接接RS232电平!),可接单片机的RXD3GND地4VCC电源(2.7V~5.0V)表1.1ATK-NEO-6M模块各引脚功能描述另外,模块自带了一个状态指示灯:PPS。该指示灯连接在UBLOXNEO-6M模组的TIMEPULSE端口,该端口的输出特性可以通过程序设置。PPS指示灯,在默认条件下(没经过程序设置),有2个状态:1,常亮,表示模块已开始工作,但还未实现定位。2,闪烁(100ms灭,900ms亮),表示模块已经定位成功。这样,通过PPS指示灯,我们就可以很方便的判断模块的当前状态,方便大家使用。ATK-NEO-6M模块默认采用NMEA-0183协议输出GPS定位数据,并可以通过UBX协议对模块进行配置,NMEA-0183协议详细介绍请参考《ATK-NEO-6M用户手册.pdf》,UBX配置协议,请参考《u-blox6_ReceiverDescriptionProtocolSpec_GPS.G6-SW-10018-C.pdf》。通过ATK-NEO-6MGPS模块,任何单片机(3.3V/5V电源)都可以很方便的实现GPS定位,当然他也可以连接电脑,利用电脑软件实现定位。ATK-NEO-6M-V12GPS模块的原理图如图1.2所示:图1.2ATK-NEO-6MGPS模块原理图2、硬件连接本实验功能简介:通过串口2连接ATK-NEO-6MGPS模块,然后通过液晶显示GPS信息,包括精度、纬度、高度、速度、用于定位的卫星数、可见卫星数、UTC时间等信息。同时,可以通过USMART工具,设置GPS模块的刷新速率(最大支持5Hz刷新)和时钟脉冲的配置。另外,通过KEY0按键,可以开启或关闭NMEA数据的上传(即输出到串口1,方便开发调试)。所要用到的硬件资源如下:1,指示灯DS02,KEY0按键3,串口1、串口24,TFTLCD模块5,ATK-NEO-6MGPS模块接下来,我们看看ATK-NEO-6MGPS模块同ALIENTEKSTM32开发板的连接,前面我们介绍了ATK-NEO-6M模块的接口,我们通过杜邦线连接模块和开发板的相应端口,连接关系如表2.1所示:ATK-NEO-6MGPS模块与开发板连接关系ATK-NEO-6MGPS模块VCCGNDTXDRXDALIENTEKSTM32开发板3.3V/5VGNDPA3PA2表2.1ATK-NEO-6M模块同ALIENTEKSTM32开发板连接关系表表中ATK-NEO-6MGPS模块的VCC,因为我们的模块是可以3.3V或5V供电的,所以可以接开发板的3.3V电源,也可以接开发板的5V电源,这个随便大家自己选择。模块与开发板的连接是很简单,不过这里特别提醒大家:1,请把GPS模块放到窗户边/阳台,否则可能收不到GPS信号。2,如果想在室内开发,可以考虑使用ALIENTEK提供的蓝牙串口模块(ATK-HC05),这样,我们可以将GPS放到户外/窗口,而仍然在室内进行程序的调试开发。3、软件实现本实验(注:这里仅以战舰板代码为例进行介绍,MiniSTM32开发板对应代码几乎一模一样,详见MiniSTM32开发板扩展实验23),我们在扩展例程1:ATK-HC05蓝牙串口模块实验的基础上修改,在HARDWARE文件夹里面新建一个GPS文件夹,并新建gps.c,gps.h两个文件。然后在工程HARDWARE组里面添加gps.c,并在工程添加gps.h的头文件包含路径。在gps.c里面,我们输入如下代码:#includegps.h#includeled.h#includedelay.h#includeusart2.h#includestdio.h#includestdarg.h#includestring.h#includemath.h//从buf里面得到第cx个逗号所在的位置//返回值:0~0XFE,代表逗号所在位置的偏移.//0XFF,代表不存在第cx个逗号u8NMEA_Comma_Pos(u8*buf,u8cx){u8*p=buf;while(cx){if(*buf=='*'||*buf''||*buf'z')return0XFF;//遇到'*'或非法字符,则不存在第cx个逗号if(*buf==',')cx--;buf++;}returnbuf-p;}//m^n函数//返回值:m^n次方.u32NMEA_Pow(u8m,u8n){u32result=1;while(n--)result*=m;returnresult;}//str转换为数字,以','或者'*'结束//buf:数字存储区//dx:小数点位数,返回给调用函数//返回值:转换后的数值intNMEA_Str2num(u8*buf,u8*dx){u8*p=buf;u32ires=0,fres=0;u8ilen=0,flen=0,i;u8mask=0;intres;while(1)//得到整数和小数的长度{if(*p=='-'){mask|=0X02;p++;}//是负数if(*p==','||(*p=='*'))break;//遇到结束了if(*p=='.'){mask|=0X01;p++;}//遇到小数点了elseif(*p'9'||(*p'0'))//有非法字符{ilen=0;flen=0;break;}if(mask&0X01)flen++;elseilen++;p++;}if(mask&0X02)buf++;//去掉负号for(i=0;iilen;i++)ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');//得到整数部分数据if(flen5)flen=5;//最多取5位小数*dx=flen;//小数点位数for(i=0;iflen;i++)//得到小数部分数据{fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');}res=ires*NMEA_Pow(10,flen)+fres;if(mask&0X02)res=-res;returnres;}//分析GPGSV信息//gpsx:nmea信息结构体//buf:接收到的GPS数据缓冲区首地址voidNMEA_GPGSV_Analysis(nmea_msg*gpsx,u8*buf){u8*p,*p1,dx;u8len,i,j,slx=0;u8posx;p=buf;p1=(u8*)strstr((constchar*)p,$GPGSV);len=p1[7]-'0';//得到GPGSV的条数posx=NMEA_Comma_Pos(p1,3);//得到可见卫星总数if(posx!=0XFF)gpsx-svnum=NMEA_Str2num(p1+posx,&dx);for(i=0;ilen;i++){p1=(u8*)strstr((constchar*)p,$GPGSV);for(j=0;j4;j++){posx=NMEA_Comma_Pos(p1,4+j*4);if(posx!=0XFF)gpsx-slmsg[slx].num=NMEA_Str2num(p1+posx,&dx);//得到卫星编号elsebreak;posx=NMEA_Comma_Pos(p1,5+j*4);if(posx!=0XFF)gpsx-slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角elsebreak;posx=NMEA_Comma_Pos(p1,6+j*4);if(posx!=0XFF)gpsx-slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角elsebreak;posx=NMEA_Comma_Pos(p1,7+j*4);if(posx!=0XFF)gpsx-slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx);//得到卫星信噪比elsebreak;slx++;}p=p1+1;//切换到下一个GPGSV信息}}//分析GPGGA信息//gpsx:nmea信息结构体//buf:接收到的GPS数据缓冲区首地址voidNMEA_GPGGA_Analysis(nmea_msg*gpsx,u8*buf){u8*p1,dx;u8posx;p1=(u8*)strstr((constchar*)buf,$GPGGA);posx=NMEA_Comma_Pos(p1,6);//得到GPS状态if(posx!=0XFF)gpsx-gpssta=NMEA_Str2num(p1+posx,&dx);posx=NMEA_Comma_Pos(p1,7);//得到用于定位的卫星数if(posx!=0XFF)gpsx-posslnum=NMEA_Str2num(p1+posx,&dx);posx=NMEA_Comma_Pos(p1,9);//得到海拔高度if(posx!=0XFF)gpsx-altitude=NMEA_Str2num(p1+posx,&dx);}//分析GPGSA信息//gpsx:nmea信息结构体//buf:接收到的GPS数据缓冲区首地址voidNMEA_GPGSA_Analysis(nmea_msg*gpsx,u8*buf){u8*p1,dx;u8posx;u8i;p1=(u8*)strstr((constchar*)buf,$GPGSA);posx=NMEA_Comma_Pos(p1,2);//得到定位类型if(posx!=0XFF)gpsx-fixmode=NMEA_Str2num(p1+posx,&dx);for(i=0;i12;i++)//得到定位卫星编号{posx=NMEA_Comma_Pos(p1,3+i);if(posx!=0XFF)gpsx-possl[i]=NMEA_Str2num(p1+posx,&dx);elsebreak;}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,&