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));
}
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));
}
举报