stm32单片机串口接收GPS数据并解析NMEA之GPRMC
2018-10-06 来源:eefocus
程序主要实现对GPRMC数据的全解析,解析包括时间解析,位置解析,航向,组合,定位状态等等的解析
直接利用stm32系列单片机对GPS板卡接收到的数据进行处理得到相对应的信息
一. gps.h文件:
#ifndef __GPS_H
#define __GPS_H
#include 'delay.h'
#include 'sys.h'
#include 'usart.h'
extern u8 gps_buf[120]; //用来接收串口数据
extern u8 gps_i ;
enum gps_rece_state //串口数据的枚举类型
{
f_start, //帧开始
f_segment, //字段接收完
f_end,
f_out
};
extern enum gps_rece_state gps_state;
void send_gps(void);
void send_route(void);
void send_speed(void);
#endif
二. gps.c文件如下:
#include 'gps.h'
#include 'stm32f10x_usart.h'
#include 'lcd.h'
#include 'global.h'
#include 'config.h'
#include 'led.h'
#include 'myfun.h'
#include 'include.h'
//采集串口数据,并且读取得到GPS数据
u8 gps_buf[120] = {0}; //用来接收串口数据
u8 gps_i = 0;
u8 comma = 0;
u8 check_count = 0;
enum gps_rece_state gps_state; //串口接收gps的状态
void get_gps(void);
//{
// f_start, //帧开始
// f_segment, //字段接收完
// f_end,
// f_out
//}
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 rec = 0,i;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
rec =USART_ReceiveData(USART3);
if(rec == '$') //如果是美元符,为起始
{
gps_state = f_start;
gps_i = 0;
comma = 0;
check_count = 0;
for(i=0;i<120;i++)
gps_buf[i] = 0;
}
else if(gps_state == f_start) //开始接收
{
gps_buf[gps_i] = rec;
gps_i++;
if(rec == ',')
comma++;
if(comma == 12)
gps_state = f_segment;//还剩下四个字节校验值
}
else if(gps_state == f_segment) //开始接收
{
gps_buf[gps_i] = rec;
gps_i++; //此时的数组这个位置刚好没写
check_count++;
if(check_count == 4)
gps_state = f_end;
}
else if(gps_state == f_end) //接收完成
{
#ifdef SHOW_GPS
LCD_Fill(0,0,239,50,WHITE);
LCD_ShowString(0,0,gps_buf);
#endif
get_gps();
}
}
}
//从串口中得到GPS的数据和显示数据
//使用数组存逗号位置
u8 pos[13] = {0};
void get_gps(void)
{
u8 i,j = 0;
if((gps_buf[0]=='G')&&(gps_buf[1]=='P')&&(gps_buf[2]=='R')\
&&(gps_buf[3]=='M')&&(gps_buf[4]=='C'))
{
for(i = 5;i < gps_i;i++)
{
if(gps_buf[i] == ',')
pos[++j] = i;//第j个逗号在第i个位置
}
ori_data.status = gps_buf[pos[2]+1];
screen.status = gps_buf[pos[2]+1];
if(ori_data.status == 'A')
{
LED0 = 0;
for(i = pos[3]+1;i < pos[4];i++) //纬度
{
screen.lat[i-pos[3]-1] = gps_buf[i];
//
}
ori_data.lat = asc2f(screen.lat)/100;
screen.ns = gps_buf[pos[4]+1];
ori_data.ns = gps_buf[pos[4]+1];
for(i = pos[5]+1;i < pos[6];i++) //经度
screen.lon[i-pos[5]-1] = gps_buf[i];
ori_data.lon = asc2f(screen.lon)/100;
screen.ew = gps_buf[pos[6]+1];
ori_data.ew = gps_buf[pos[6]+1];
for(i = pos[7]+1;i < pos[8];i++) //地面速度
screen.speed[i-pos[7]-1] = gps_buf[i];
ori_data.speed = 0.5144 * asc2f(screen.speed);
for(i = pos[8]+1;i < pos[9];i++) //地面航向
screen.azimuth[i-pos[8]-1] = gps_buf[i];
ori_data.azimuth = asc2f(screen.azimuth);
for(i = pos[10]+1;i < pos[11];i++) //磁偏角 磁偏角方向
screen.declination[i-pos[10]-1] = gps_buf[i];
ori_data.declination = asc2f(screen.declination);
// for(i = pos[11]+1;i < pos[12];i++) //
if((pos[12] - pos[11]-1)!=0)
screen.dir_declination = gps_buf[pos[11]+1];
ori_data.dir_declination = screen.dir_declination;
}
else
{
LED0 = 1;
}
}
}
//发送GPS数据原始帧格式
void send_gps(void)
{
uint64_t time_now_us = time_nowUs();
float time_s = time_now_us* (1.0f/1e6f);
while(SCI_SendChar('I'));
SCISendInt(speed_east*100);
while(SCI_SendChar('|'));
SCISendInt(speed_north*100);
while(SCI_SendChar('|'));
SCISendInt(speed_hor*100);
while(SCI_SendChar('|'));
SCISendInt(0);
while(SCI_SendChar('|'));
SCISendInt(time_s*10);
while(SCI_SendChar('|'));
SCISendInt(0);
while(SCI_SendChar('\r'));
while(SCI_SendChar('\n'));
}
//发送数据,经纬度,速度等等
void send_speed(void)
{
uint64_t time_now_us = time_nowUs();
float time_s = time_now_us* (1.0f/1e6f);
u8 i;
while(SCI_SendChar('I'));
// double2asc(g_lat);
double2asc(ori_data.speed);
for(i = 1;asc_d[i]!=0;i++) //GPS
USART_SendChar(USART1,asc_d[i]);
while(SCI_SendChar('|'));
// double2asc(g_lon);
double2asc(speed_imu);
for(i = 1;asc_d[i]!=0;i++) //IMU
USART_SendChar(USART1,asc_d[i]);
while(SCI_SendChar('|'));
float2asc(speed_hor);
for(i = 1;((asc_f[i]!=0)&&(i<6));i++) //组合
USART_SendChar(USART1,asc_f[i]);
while(SCI_SendChar('|'));
float2asc(yaw_north);
for(i = 1;((asc_f[i]!=0)&&(i<6));i++) //航向
USART_SendChar(USART1,asc_f[i]);
while(SCI_SendChar('|'));
SCISendInt(time_s*10);
while(SCI_SendChar('|')); //定位状态
//if(ori_data.status == 'A')
if(pos_mode == 3)
USART_SendChar(USART1,'1');
else
USART_SendChar(USART1,'0');
while(SCI_SendChar('\r'));
while(SCI_SendChar('\n'));
}
//发送数据,经纬度,速度等等
void send_route(void)
{
uint64_t time_now_us = time_nowUs();
int time_s = (int)time_now_us* (1.0f/1e6f);
u8 i;
while(SCI_SendChar('I'));
double2asc(g_lat);
for(i = 1;asc_d[i]!=0;i++) //纬度
USART_SendChar(USART1,asc_d[i]);
while(SCI_SendChar('|'));
double2asc(g_lon);
for(i = 1;asc_d[i]!=0;i++) //经度
USART_SendChar(USART1,asc_d[i]);
while(SCI_SendChar('|'));
float2asc(speed_hor);
for(i = 1;((asc_f[i]!=0)&&(i<6));i++) //速度
USART_SendChar(USART1,asc_f[i]);
while(SCI_SendChar('|'));
float2asc(course);
for(i = 1;((asc_f[i]!=0)&&(i<6));i++) //航向
USART_SendChar(USART1,asc_f[i]);
while(SCI_SendChar('|'));
SCISendInt(time_s*10);
while(SCI_SendChar('|')); //定位状态
if(pos_mode == 3)
USART_SendChar(USART1,'1');
else
USART_SendChar(USART1,'0');
// if(ori_data.status == 'A')
// USART_SendChar(USART1,'1');
// else
// USART_SendChar(USART1,'0');
while(SCI_SendChar('\r'));
while(SCI_SendChar('\n'));
}
由于部分代码显示不全面,,可参考源代码下载地址:
链接:https://pan.baidu.com/s/1y7xDSfy2Ftv4p9PJRxCmSA 密码:1v7g
三、官方的解析NMEA数据的标准库文件的详细目录如下:
--------------------------------------------------------------
│ 1.txt
│ CHANGELOG.TXT
│ LICENSE.TXT
│ Makefile
│ nmea.ico
│ nmea.sln
│ README.TXT
│
├─build
├─doc
│ makefile
│ nmea.doxygen
│
├─include
│ └─nmea
│ config.h
│ context.h
│ generate.h
│ generator.h
│ gmath.h
│ info.h
│ nmea.h
│ parse.h
│ parser.h
│ sentence.h
│ time.h
│ tok.h
│ units.h
│
├─lib
├─samples
│ ├─generate
│ │ generate.vcproj
│ │ main.c
│ │
│ ├─generator
│ │ generator.vcproj
│ │ main.c
│ │
│ ├─math
│ │ main.c
│ │ math.vcproj
│ │
│ ├─parse
│ │ main.c
│ │ parse.vcproj
│ │
│ └─parse_file
│ gpslog.txt
│ main.c
│ parse_file.vcproj
│
└─src
context.c
generate.c
generator.c
gmath.c
info.c
nmea.vcproj
parse.c
parser.c
sentence.c
time.c
tok.c
--------------------------------------------------------------
主要提供各种GPS,数据的解析,使用C语言编写,可以解析GPGGA,GPRMC,GPZDA等等数据,方便移植到下位机当中
下载地址如下 :
链接:https://pan.baidu.com/s/1KM5y30wge4Im-2jfI7Ihfw密码:c0p2