STM32
直播中

vinww特烦恼

8年用户 1035经验值
擅长:存储技术
私信 关注
[问答]

GPS数据格式是由哪些部分组成的

GPS数据格式是由哪些部分组成的?
怎样编写GPS结构体用来存放接收GPRMC缓存和提取经纬度信息呢?

回帖(1)

李广旭

2021-12-9 15:36:16
1.GPS数据格式


帧格式形如: a a c c c , d d d , d d d , … , d d d ∗ h h ( C R ) ( L F ) 1 、 “ aaccc,ddd,ddd,…,ddd*hh(CR)(LF) 1、 “aaccc,ddd,ddd,…,ddd∗hh(CR)(LF)1、“” :帧命令起始位
2、 aaccc:地址域,前两位为识别符(aa),后三位为语句名(ccc)
3、 ddd…ddd:数据
4、 “” :校验和前缀(也可以作为语句数据结束的标志)
5、 hh:校验和(check sum), $与之间所有字符ASCII码的校验和(各字节做异或运算,得到
校验和后,再转换16进制格式的ASCII字符)
6、 (CR)(LF):帧结束,回车和换行符


一帧数据格式
$GPRMC,032524.00,A,2303.00591,N,11324.42138,E,0.689,270814,D7E
$GPVTG,T,M,0.689,N,1.276,K,D23
$GPGGA,032524.00,2303.00591,N,11324.42138,E,2,12,0.78,13.2,M,-5.1,M,00007E
$GPGSA,A,3,01,11,08,30,07,32,13,42,28,04,27,17,1.18,0.78,0.8901
$GPGSV,5,1,17,01,69,151,35,04,34,198,31,07,75,258,26,08,79,286,1674
$GPGSV,5,2,17,11,77,052,28,13,15,203,20,16,07,101,17,15,254,2774
$GPGSV,5,3,17,19,29,036,40,20,12,162,23,04,181,08,27,06,052,157A
$GPGSV,5,4,17,28,21,314,19,30,49,311,17,32,10,122,20,42,50,128,3973
$GPGSV,5,5,17,50,45,122,334A
$GPGLL,2303.00591,N,11324.42138,E,032524.00,A,D68


串口接收流程
定义GPS数据结构体
typedef struct SaveData
{
char GPS_Buffer[GPS_Buffer_Length];
char isGetData;
char isParseData;
char UTCTime[UTCTime_Length];
char latitude[latitude_Length];
char N_S[N_S_Length];
char longitude[longitude_Length];
char E_W[E_W_Length];
char isUsefull;
} _SaveData;


只接收$GPRMC的内容


开启串口接收中断,接收一个字符存入res中
在串口中断回调函数中,判断当接收到‘$’时是接收到新的一行,u16 point为0
将每次回调接收的res存入 USART_RX_BUF[point]中,[USART_REC_LEN最大200]
判定当USART_RX_BUF[0] == 'KaTeX parse error: Expected 'EOF', got '&' at position 3: ' &̲& USART_RX_BUF[…GPRMC行时
当res==‘n’,即一行结束
将USART_RX_BUF,中point1长的数据存入char GPS_Buffer[GPS_Buffer_Length=80]中,在存入之前要将GPS_Buffer全部清空
判定GPS获得数据isGetData=true,point长度清空, USART_RX_BUF[USART_REC_LEN]清空
如果point >= USART_REC_LEN,point= USART_REC_LEN;
解析GPS数据
如果isGetData==true,令其复为false,打印输出GPS_Buffer以供查看
$GPRMC,032525.00,A,2303.00594,N,11324.42136,E


通过提取subString=strstr(GPS_Buffer, “,”),循环6次
2. 当第一次循环,找不到,时报错errorLog(1);输出error 1;
3. 如果第一次能找到,subString+1到逗号之后
4. 再令subStringNext = strstr(subString, “,”)下一个逗号,如果找不到,则报错2
5. 将每一个从subString开始subStringNext - subString范围的数据依次memcpy存入时间,有效,维度,N,经度,E中
6. 判定isParseData=true解析完成,如果有效为A,isUsefull = true,否则为false
7. 打印GPS数据中各个成员,判定是否有效,如果无效,给定一个默认值


gps.h
编写GPS结构体用来存放接收GPRMC缓存和提取经纬度信息


#define GPS_Buffer_Length 80
#define true 1
#define false 0
#define        latitude_Length 10
#define longitude_Length 11
typedef struct GPS_Data
{
char GPS_Buffer[GPS_Buffer_Length];
char isGetData;
char isUseful;
char latitude[latitude_Length];
char longitude[longitude_Length];
}_GPS_Data;
/
void user_common_init(void);//开启串口接收中断,初始化结构体
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//接收缓存
void parseGPS(void);//解析提取经纬度
void printGPS(void);//判断A/V是否有效,否则输出默认经纬度
extern _GPS_Data GPSData;


GPS.c
#define u8 uint8_t
#define u16 uint16_t
u8 rdata[1];
u8 rdata1[1];
u16 point;


#define RX_BUF_MAXLEN 200
char USART_RX_BUF[RX_BUF_MAXLEN];
_GPS_Data GPSData;
u8 latitude[]="2303.00591";
u8 longitude[]="11324.42138";


void user_common_init(void)
{       
        do{
        }while(HAL_OK!=HAL_UART_Receive_IT(&huart5,(u8*)&rdata,1));//开启接收中断
        //清空GPSData
        memset(GPSData.GPS_Buffer,0,GPS_Buffer_Length);
        memset(GPSData.latitude,0,latitude_Length);
        memset(GPSData.longitude,0,longitude_Length);
        GPSData.isGetData=false;
        GPSData.isUseful=false;
        //清空串口发送协议的起止符
        serial_rx_data.syn=serial_rx_data.syn_CR=serial_rx_data.syn_LF=serial_rx_data.type=0;               
}


//接收$GPRMC存入GPSData.buffer
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
        u8 rec;
        if(huart->Instance==UART5)
        {
                rec=rdata[0];
                if(rec=='$')
                {
                        point=0;
                }
                USART_RX_BUF[point++]=rec;
                if(USART_RX_BUF[0]=='$'&&USART_RX_BUF[4]=='M'&&USART_RX_BUF[5]=='C')
                {
                        if(rec=='n')
                        {
                                memset(GPSData.GPS_Buffer,0,GPS_Buffer_Length);
                                memcpy(GPSData.GPS_Buffer,USART_RX_BUF,point);
                                memset(USART_RX_BUF,0,RX_BUF_MAXLEN);
                                GPSData.isGetData=true;
                                point=0;
                        }
                }
                if(point>=RX_BUF_MAXLEN)
                {
                        point=RX_BUF_MAXLEN;
                }
                HAL_UART_Receive_IT(&huart5,(u8*)&rdata,1);
        }               
}
//解析GPS
void parseGPS()
{
        char *subString;
        char *subNext;
        if(GPSData.isGetData)
        {
                GPSData.isGetData=false;
                //HAL_UART_Transmit(&huart1,(u8*)GPSData.GPS_Buffer,sizeof(GPSData.GPS_Buffer),1000);
                for(int i=0;i<9;i++)
                {
                        if((subString=strstr(GPSData.GPS_Buffer,","))!=NULL)
                        {                               
                                subString++;
                                if((subNext=strstr(subString,","))!=NULL)
                                {
                                        char usefullBuffer[2];
                                        switch(i)
                                        {
                                                case 1:memcpy(usefullBuffer,subString,subNext-subString);
                                                case 2:memcpy(GPSData.latitude,subString,subNext-subString); break;
                                                case 4:memcpy(GPSData.longitude,subString,subNext-subString); break;
                                                default:break;
                                        }
                                        subString=subNext;


                                        if(usefullBuffer[0]=='A')
                                                GPSData.isUseful=true;
                                        else if(usefullBuffer[0]=='V')                       
                                        {
                                                GPSData.isUseful=false;
                                       
                                        }
                                }
                        }
                }
        }
}
//使用默认
void printGPS()
{
        parseGPS();
        if(!GPSData.isUseful)//如果无效,则使用默认GPS
        {
                memcpy(GPSData.latitude,latitude,sizeof(latitude));
                memcpy(GPSData.longitude,longitude,sizeof(longitude));
        }
        GPSData.isGetData=false;       
        }       
}


串口发送协议
使用结构体和枚举型,选择不同类型TYPE数据发送


#ifndef _USER_PROTCOL_H_
#define _USER_PROTCOL_H_


#include "stdio.h"


/*protcol*/
enum _ptl_type
{
        VAL_START=0,
        VAL_POSE,
        VAL_IMU_RAW,
        VAL_VEL,
        VAL_PID,
        VAL_IMU,
        VAL_GPS,
        VAL_END
};


#define _SERIAL_SYN_CODE_START 0XFA
#pragma pack(1)
typedef struct _serial_data
{
        uint8_t syn;
        uint8_t type;
        union{
                struct{
                        float liner[3],angular[3];
                }vel;
                struct{
                        bool rot_ok,acc_ok,mag_ok;
                        double rot[3],acc[3],mag[3];
                }imu;       
                struct{
                        char latitude[11],longitude[12];
                }gps;
                float pid[3];
        }dat;
        uint8_t syn_CR;
        uint8_t syn_LF;
}serialData;
#pragma pack()
#endif


发送
void serial2_ros_data()
{
        static serialData data;
        data.syn=_SERIAL_SYN_CODE_START;
        data.syn_CR='r';
        data.syn_LF='n';
        float *quar_rpy;
/*************************************VEL*********************************************/
        while(HAL_UART_GetState(&huart4)==HAL_UART_STATE_BUSY_TX_RX) {}
        data.type=VAL_POSE;
        data.dat.vel.liner[0]=xrobot->robot_linear_vel_x;
        data.dat.vel.liner[1]=0;
          data.dat.vel.liner[2]=0;       
          HAL_UART_Transmit_DMA(&huart4,(uint8_t*)&data,sizeof(serialData));
/******************************************IMU*************************************/
          quar_rpy=imu_print();
          while(HAL_UART_GetState(&huart4)==HAL_UART_STATE_BUSY_TX_RX){}  
          data.type=VAL_IMU;       
          data.dat.vel.angular[0]=quar_rpy[0];
          data.dat.vel.angular[1]=quar_rpy[1];
          data.dat.vel.angular[2]=quar_rpy[2];
        HAL_UART_Transmit_DMA(&huart4,(uint8_t*)&data,sizeof(data));
/***************************GPS***********************/
        while(HAL_UART_GetState(&huart4)==HAL_UART_STATE_BUSY_TX_RX){}       
        data.type=VAL_GPS;
        memcpy(data.dat.gps.latitude,        GPSData.latitude,sizeof(GPSData.latitude));       
        memcpy(data.dat.gps.longitude,        GPSData.longitude,sizeof(GPSData.longitude));       
        HAL_UART_Transmit_DMA(&huart4,(uint8_t*)&data,sizeof(serialData));
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分