项目中使用到了正点原子的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倍,实际要除以100000
u8 nshemi; //北纬/南纬,N:北纬;S:南纬
u32 longitude; //经度 分扩大100000倍,实际要除以100000
u8 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.0
u16 hdop; //水平精度因子 0~500,对应实际值0~50.0
u16 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波特率为9600
SkyTra_Cfg_Prt(3); //设置定位模块的波特率为38400
usart3_init(38400); //重新初始化串口3波特率为38400
key=SkyTra_Cfg_Tp(100000); //脉冲宽度为100ms
}
while(SkyTra_Cfg_Rate(5)!=0&&key!=0); //配置SkyTraF8-BD的更新速率为5Hz
LCD_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);
}
|