单片机
返回首页

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


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章