项目中使用到了正点原子的ATK-S1216F8 GPS/BD双模定位模块,本文记录使用单片机读取其数据的过程。
首先main.c中需要调用已经写好的定位头文件:
#include "gps.h"
在主函数中会用到该头文件中定义好的结构体nmea_msg:
__packed typedef struct
{ u8 svnum; //可见GPS卫星数u8 beidou_svnum; //可见GPS卫星数nmea_slmsg slmsg[12]; //最多12颗GPS卫星beidou_nmea_slmsg beidou_slmsg[12]; //暂且算最多12颗北斗卫星nmea_utc_time utc; //UTC时间u32 latitude; //纬度 分扩大100000倍,实际要除以100000u8 nshemi; //北纬/南纬,N:北纬;S:南纬 u32 longitude; //经度 分扩大100000倍,实际要除以100000u8 ewhemi; //东经/西经,E:东经;W:西经u8 gpssta; //GPS状态:0,未定位;1,非差分定位;2,差分定位;6,正在估算. u8 posslnum; //用于定位的GPS卫星数,0~12.u8 possl[12]; //用于定位的卫星编号u8 fixmode; //定位类型:1,没有定位;2,2D定位;3,3D定位u16 pdop; //位置精度因子 0~500,对应实际值0~50.0u16 hdop; //水平精度因子 0~500,对应实际值0~50.0u16 vdop; //垂直精度因子 0~500,对应实际值0~50.0 int altitude; //海拔高度,放大了10倍,实际除以10.单位:0.1m u16 speed; //地面速率,放大了1000倍,实际除以10.单位:0.001公里/小时
}nmea_msg;
整个代码的逻辑为:设置定位模块的波特率——>初始化串口为相应波特率——>判断是否接收到数据——>若接收到,则赋值转移数据——>分析接收到的数据,并赋给结构体
参考代码:
#include "gps.h" //调用GPS头文件
#include "lcd.h" //显示屏,用于显示数据和提示
#include "usart3.h" //使用stm32上的USART3串口来接收定位模块的数据nmea_msg gpsx; //定义结构体int main(void)
{u8 buffer[600] //转移缓冲区的数据,最大600个字节.LCD_Init();if(SkyTra_Cfg_Rate(5)!=0) //设置定位信息更新速度为5Hz,判断GPS模块是否在位. {LCD_ShowString(30,120,200,16,16,"SkyTraF8-BD Setting...");//该句用于提示do{usart3_init(9600); //初始化串口3波特率为9600SkyTra_Cfg_Prt(3); //设置定位模块的波特率为38400usart3_init(38400); //重新初始化串口3波特率为38400key=SkyTra_Cfg_Tp(100000); //脉冲宽度为100ms}while(SkyTra_Cfg_Rate(5)!=0&&key!=0); //配置SkyTraF8-BD的更新速率为5HzLCD_ShowString(30,120,200,16,16,"SkyTraF8-BD Set Done!!");delay_ms(500);LCD_Fill(30,120,30+200,120+16,WHITE); //清除显示 }while(1){if(USART3_RX_STA&0X8000) //接收到一次数据了{rxlen=USART3_RX_STA&0X7FFF; //得到数据长度for(k=0;k<rxlen;k++) buffer[k]=USART3_RX_BUF[k]; //将数据从串口缓冲区中取出USART3_RX_STA=0; //启动下一次接收GPS_Analysis(&gpsx,(u8*)buffer); //分析字符串Gps_Msg_Show(); //显示信息 }}
}
注:
1. UART3_RX_STA的各位含义:
2. 给结构体赋值的关键函数GPS_Analysis(nmea_msg *gpsx,u8 *buf):
//提取NMEA-0183信息
//gpsx:nmea信息结构体
//buf:接收到的GPS数据缓冲区首地址
void GPS_Analysis(nmea_msg *gpsx,u8 *buf)
{NMEA_GPGSV_Analysis(gpsx,buf); //GPGSV解析NMEA_BDGSV_Analysis(gpsx,buf); //BDGSV解析NMEA_GNGGA_Analysis(gpsx,buf); //GNGGA解析 NMEA_GNGSA_Analysis(gpsx,buf); //GPNSA解析NMEA_GNRMC_Analysis(gpsx,buf); //GPNMC解析NMEA_GNVTG_Analysis(gpsx,buf); //GPNTG解析
}
3. 附自定义函数Gps_Msg_Show(void):
void Gps_Msg_Show(void)
{float tp; POINT_COLOR=BLUE; tp=gpsx.longitude; sprintf((char *)dtbuf,"Longitude:%.5f %1c ",tp/=100000,gpsx.ewhemi);//得到经度字符串LCD_ShowString(30,140,200,16,16,dtbuf); tp=gpsx.latitude; sprintf((char *)dtbuf,"Latitude:%.5f %1c ",tp/=100000,gpsx.nshemi);//得到纬度字符串LCD_ShowString(30,160,200,16,16,dtbuf); tp=gpsx.altitude; sprintf((char *)dtbuf,"Altitude:%.1fm ",tp/=10); //得到高度字符串LCD_ShowString(30,180,200,16,16,dtbuf); tp=gpsx.speed; sprintf((char *)dtbuf,"Speed:%.3fkm/h ",tp/=1000); //得到速度字符串 LCD_ShowString(30,200,200,16,16,dtbuf); if(gpsx.fixmode<=3) //定位状态{ sprintf((char *)dtbuf,"Fix Mode:%s",fixmode_tbl[gpsx.fixmode]); LCD_ShowString(30,220,200,16,16,dtbuf); }//用于定位的GPS卫星数 sprintf((char *)dtbuf,"GPS+BD Valid satellite:%02d",gpsx.posslnum); LCD_ShowString(30,240,200,16,16,dtbuf); //可见GPS卫星数 sprintf((char *)dtbuf,"GPS Visible satellite:%02d",gpsx.svnum%100); LCD_ShowString(30,260,200,16,16,dtbuf);//可见北斗卫星数sprintf((char *)dtbuf,"BD Visible satellite:%02d",gpsx.beidou_svnum%100);LCD_ShowString(30,280,200,16,16,dtbuf);sprintf((char *)dtbuf,"UTC Date:%04d/%02d/%02d ",gpsx.utc.year,gpsx.utc.month,gpsx.utc.date);//显示UTC日期LCD_ShowString(30,300,200,16,16,dtbuf); sprintf((char *)dtbuf,"UTC Time:%02d:%02d:%02d ",gpsx.utc.hour,gpsx.utc.min,gpsx.utc.sec);//显示UTC时间LCD_ShowString(30,320,200,16,16,dtbuf);
}