历史上的今天
今天是:2024年10月06日(星期日)
2018年10月06日 | 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
史海拾趣
|
1、是安全性:在选择灯具时不能一味地贪便宜,而要先看其质量,检查质保书、合格证是否齐全。有时最贵的并不一定是最好的,但太廉价的一定是不好的。很多便宜灯质量不过关,往往隐患无穷,一旦发生火灾,后果不堪设想。 2、看启动性能:若 ...… 查看全部问答> |
|
我的IAP程序地址空间0x8000000-0x8004000 开机后进入IAP,判断是否满足IAP的条件,如果否则进入APP;我的APP用的 ucOS;在 APP里检测到上位机的IAP请求时程序跳转到IAP;但是在IAP里却不能响应中断?IAP和APP程序入口都进行中断端口重映射了!请问 ...… 查看全部问答> |
|
不久前在IC-china的展会上看到上海高通的蓝牙拨号器升级方案,后来在最近几天的中国电子展上也看到了中电的蓝牙拨号器方案,貌似现在这个东西特别火哦~~据说都装了上海高通的字库芯片,现在可以同步电话目录和短信了,还配合小键盘输入法(好像也是 ...… 查看全部问答> |
|
在电子世界领域,从20世纪中的无线电时代也进入到21世纪以计算机技术为 中心的智能化现代电子系统时代。现代电子系统的基本核心是嵌入式计算机 系统(简称嵌入式系统),而单片机是最典型、最广泛、最普及的嵌入式系统 。下面就由福州卓跃教育就单 ...… 查看全部问答> |
|
【学习Sitara™ AM335x】-把Beaglebone变成一个高清晰度IP摄像头 需要习惯于看英文哦,原文地址: http://www.oz9aec.net/index.php/ ... efinition-ip-camera Few weeks ago I posted some notes about using the Logitech HD Pro Webcam C920 with Gstreamer. I have since ported the setup to the Beaglebon ...… 查看全部问答> |




