📄 handlegpsdata.c
字号:
/********************************************************************************************
//程序名称: GPS数据处理模块程序
//版权说明: GPS数据处理模块DEBUG版本
//版本号: V1.0
//功能: 控制GPS模块电源开关,从GPS模块缓冲区中读取数据,处理最小推荐帧格式数据,并以十六进制数据格式进行存放
//开发人: 谢忠铭
//开发时间:
//修改者: 唐均
//修改时间 2008年7月9日
//修改简要说明: 1.进行GPS模块电源控制,2.修改读取GPS数据出现的丢包,读取不完整现象.3.使用回调机制,方便实现对不同数据帧类型处理.
//其他:
修改记录:
********************************************************************************************/
/**************************************头文件************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include "HandleGpsData.h"
#include "io.h"
#include "ControlIo.h"
/*********************************************************************************************/
//#define DATA_PACKET_TEST
#define GPSDATA_MAIN main
int nmea_fd = -1;
char ttyS0_Gps[] = {"/dev/ttyS3"};
GPS_DAT gpsdat; //存储处理后的GPS16进制数据
GPS_DAT gpsdatt; //处理GPS数据临时存储空间
GPS_NMEA_DAT *gps_nmea_dat; //存放预处理数据
#ifdef DATA_PACKET_TEST
/*===========================数据包接收测试函数========================================*/
void Data_Packet_Test(char* str,int flag)
{
FILE *fp1=NULL,*fp2=NULL;
if(flag == 0)
{
fp1=fopen("alldata.log","a+");
fprintf(fp1,"%s\n",str);
fclose(fp1);
}
if(flag == 1)
{
fp2 = fopen("rmcdata.log","a+");
fprintf(fp2,"%s\n",str);
fclose(fp2);
}
return ;
}
#endif
/*******************************************************************************************
//名称 :Dec2Hex
//功能: 十进制转换为十六制值
//输入参数:十进制整形或单字节字符型,存放十六进制整形数组
//输出参数: 无
//返回: 无
******************************************************************************************/
void Dec2Hex(int num,int temp[])
{
//int temp[8];
int i;
printf("the decimal number is %d\n",num);
for(i=7;i>=0;i--)
{
if((temp[i]=num&0x0f)>9)
temp[i] += ('A'-10);
else
temp[i] += '0';
num = num >> 4;
}
printf("the hexadecimal number is",);
for(i=0;i<8;i++)
if('0' != temp[i])
printf("%c",temp[i]);
printf("\n");
}
/*====================================GPS处理段===========================================*/
/*******************************************************************************************
//名称 :ASC2Hex
//功能: 转换字符的ASCII码为十六制值
//输入参数: 单个字符
//输出参数: 输入字符的十六进制值
//返回: 返回十六进制值
******************************************************************************************/
unsigned char ASC2Hex(unsigned char dat)
{
if(dat > '9')
dat -= 0x37;
else dat &= 0x0F;
return(dat);
}
/*====================================GPS处理段===========================================*/
/*******************************************************************************************
//名称 :SetSerial_Port
//功能: 串口配置选项初始化
//输入参数: 1.串口配置选项各成员结构体termios,2.串口传输的波特率
//输出参数: 无
//返回: 无
******************************************************************************************/
void SetSerial_Port(struct termios *GPSDATAIO,int BaudRate)
{
bzero(GPSDATAIO,sizeof(struct termios)); //清除IO口设置在
/*配置串口参数*/
GPSDATAIO->c_cflag = BaudRate|CS8|CLOCAL|CREAD; //波特率|8个数据位|本地连接|接收全能
GPSDATAIO->c_iflag = IGNPAR; //忽略帧错误和奇偶检验错误
GPSDATAIO->c_oflag = 0; //输出控制模式,为0表示输出前不要变换
GPSDATAIO->c_lflag = 0; //设置本地模式 //GPSDATAIO->c_cc[VINTR] = 0; //Ctrl-c
GPSDATAIO->c_cc[VTIME] = 0; //非 canonical 模式读时的延时,以十分之一秒为单位。
GPSDATAIO->c_cc[VMIN] = 0; //非 canonical 模式读的最小字符数。
}
/*******************************************************************************************
//名称 :Open_UartPort
//功能: 打开串口对应的设备文件,以此把设备当作文件进行读写控制操作
//输入参数: 串口对应的设备文件名,此处为"/dev/ttys3"
//输出参数: 打开设备对应的文件描述符
//返回: 成功:返回设备描述文件符 失败:返回 -1
//描述:阻塞方式读写串口,采用fcntl函数,等待数据的读入
//函数中常量注释:O_RDONLY:以可读写方式打开设备,O_NOCTTY:使这个端口不成为系统对应的控制终端,
设置该选项则系统的无法控制该进程,DEBUG时建议不设置该选项
**************************************************************************************/
int Open_UartPort( char* devname)
{
int Nmea_fd; //打开串口的文件描述符
int Err;
struct termios GPSTTYFD;
Nmea_fd=open(devname,O_RDONLY|O_NOCTTY);//可读写及屏蔽键盘等控制 |O_NOCTTY
if(Nmea_fd<0)
{
perror("Open Uart Port");
return OPENSERIALPORTFAILURE;
}
SetSerial_Port(&GPSTTYFD,B9600); //串口配置初始化
Err=tcsetattr(Nmea_fd,TCSANOW,&GPSTTYFD); //设置串口参数
if(Err=-1&&Err==EINTR)
{
perror("can't set the attribution of the terminal");
return (-1);
}
fcntl(Nmea_fd,F_SETFL,0);
//if(Err==EBADF)
//{
// return Err; //非法的文件描述符
//}
//if(Err==EINTR)
//{
// return Err; //函数调用被信号中断
//}
//if(Err==EINVAL)
//{
// return Err; //参数termios中使用了非法值
//}
//if(Err==ENCTTY)
//{
// return Err; //非终端的文件描述符
//}
return Nmea_fd;
}
/*******************************************************************************************
//名称 :Verify_Gps_Data
//功能: 无奇偶校验字符串
//输入参数: 待校验的字符串
//输出参数: 校验结果
//返回: 成功:返回0,失败:返回 -1
//无奇偶校验方法:采用逐个字符异或,最终与校验码异或,如果为0则表明校验成功,否则校验失败.
******************************************************************************************/
int Verify_Gps_Data(char* sentence)
{
int OKflag = 0,len;
unsigned char *ptGPS;
unsigned char ch,checksum = 0,chedat;
if(*sentence != '$') //判断校验数据帧第一个字符是否为NMEA协议的标志头'$'
{
return (-1);
}
len = strlen(sentence);
len-= 4;
if(len>100)
len = 100;
ptGPS = sentence + 1;
do
{
ch = *ptGPS++;
len--;
if(ch=='*')
{ /*求校验码十六进制值*/
chedat = ASC2Hex(*ptGPS);
ptGPS++;
ch = ASC2Hex(*ptGPS);
chedat<<=4;
chedat|=ch;
if(chedat!=checksum)//判断校验码是否成功
return (-1);
OKflag = 1;
break;
}
checksum^=ch; //循环相异或
}while(len>0);
if(OKflag == 0)
return (-1);
return SUCCESSVERIFYGPSDATA;// 返回校验成功标志
}
/*******************************************************************************************
//名称 : Handle_Gps_RMC
//功能: GPS数据中推荐最小数据类型处理,处理结果转换成十六进制值,放在结构体中
//输入参数: 处理的一帧RMC类型数据
//输出参数: RMC类型数据导航状态,是否为导航
//返回: 成功:返回1,导航 失败:返回0,不导航
******************************************************************************************/
int Handle_Gps_RMC(char *sentence)
{
int i, j = 0, count = 0,setflag = 0,length;
char temp,tempdot;
char *p;
p = sentence;
length = strlen(p);
printf("%s\n",sentence);
#ifdef DATA_PACKET_TEST
Data_Packet_Test(sentence,1);
#endif
memset(&gpsdatt,0,sizeof(gpsdatt)); //清空临时存取GPS导航数据缓冲
for (i = 0; i < length; )
{
temp = p[i++];
if(temp == ',') //遍历字符串,找出’,‘位置
{
count++;
}
else if(count<10)
{
switch (count)
{
case 1:
printf("========time========\n");
printf("%d ",temp);
temp &= 0x0F;
temp = (temp << 3) + (temp << 1); //小时部分的十个与个位相加,相当于temp*10+(++temp)
temp += (p[i++] & 0x0F);
printf("%d ",temp);
gpsdatt.Hour = (char)temp;
gpsdatt.Hour &= 0xFF; //转换为十六进制
//handle time.minute ASCII->HEX data
temp = p[i++];
printf("%d ",temp);
temp &= 0x0F;
temp = (temp << 3) + (temp << 1);
temp += (p[i++] & 0x0F); //分钟部分的十个与个位相加,相当于temp*10+(++temp)
printf("%x ",temp);
gpsdatt.Min = temp;
gpsdatt.Min &= 0xFF; //转换为十六进制
//handle time.second ASCII->HEX data
temp = p[i++];
printf("%d ",temp);
temp &= 0x0F;
temp = (temp << 3) + (temp << 1);
temp += (p[i++] & 0x0F); //秒钟部分的十个与个位相加,相当于temp*10+(++temp)
printf("%d ",temp);
//if(gpsdatta->Second == temp)
// temp++;
gpsdatt.Sec = temp;
gpsdatt.Sec &= 0xFF;
printf("\n%x,%x,%x\n",gpsdatt.Hour,gpsdatt.Min,gpsdatt.Sec);
break;
case 2:
if(temp == 'A') //‘A’为导航
{
gpsdatt.GpsValid = TRUE;
gpsdatt.GpsValid &= 0xFF;
setflag = 1; //设置返回的导航状态 成功导航标志1
}else if(temp == 'V') //‘V’为不导航
{
gpsdatt.GpsValid = FALSE;
gpsdatt.GpsValid &= 0xFF;
setflag = 0; //设置返回的导航状态, 不能导航标志0
return 0;
}else return(0);
printf("%x\n",gpsdatt.GpsValid);
break;
case 3:
printf("=====Latitue==========\n");
j = 1;
do
{
j++;
tempdot = p[i + j];
if(j > 8)
break;
}while(tempdot != '.');
printf("%d ",tempdot);
printf("%d ",temp);
temp &= 0x0F;
if(j > 2)
{
temp = (temp << 3) + (temp << 1); //temp = temp *10
temp += (p[i++] & 0x0F);
}
if(temp == 0)
return(0);
gpsdatt.Latitue[0] = temp;
gpsdatt.Latitue[0] &= 0xFF;
//处理纬度-分
temp = p[i++];
printf("%d ",temp);
temp &= 0x0F;
temp = (temp << 3) + (temp << 1);
temp += (p[i++] & 0x0F);
printf("%d ",temp);
gpsdatt.Latitue[1] = temp;
gpsdatt.Latitue[1] &= 0xFF;
//处理纬度-分小数
i++;
temp = p[i++];
printf("%d ",temp);
temp &= 0x0F;
temp = (temp << 3) + (temp << 1);
temp += (p[i++] & 0x0F);
printf("%d ",temp);
//temp1 = temp * 100; //高位数
gpsdatt.Latitue[2] = temp;
gpsdatt.Latitue[2] &= 0xFF;
temp = p[i++];
printf("%d ",temp);
temp &= 0x0F;
temp = (temp << 3) + (temp << 1);
temp += (p[i++] & 0x0F); //低位数
printf("%d ",temp);
//temp1 += temp;
gpsdatt.Latitue[3] = temp;
gpsdatt.Latitue[3] &= 0xFF;
//gpsdatta->Latitue_CD = temp1;
printf("%x,%x,%x,%x\n",gpsdatt.Latitue[0],gpsdatt.Latitue[1], \
gpsdatt.Latitue[2],gpsdatt.Latitue[3]);
break;
case 4:
//处理北纬
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -