GPS模块的使用
GPS代码结构
GPS模块的使用主要代码分为3部分:
1. 设置串口
2. 读取数据
3. 解析数据
串口的设置
代码
int set_com_config(int fd,int baud_rate,int data_bits,char parity,int stop_bits)
{
struct termios new_cfg,old_cfg; //termios是串口中很重要的结构体
int speed;
//保存并测试现有串口参数设置,在这里如果串口号出错,会有相关的出错信息
if(tcgetattr(fd,&old_cfg)!=0) //获取终端参数
{
perror("tcgetattr");
return -1;
}
tcflush(fd, TCIOFLUSH); //清空输入与输出缓冲区
new_cfg=old_cfg;
cfmakeraw(&new_cfg); //配置为原始模式
new_cfg.c_cflag&=~CSIZE; //屏蔽字符大小为
//设置波特率
switch(baud_rate)
{
case 2400:
{
speed = B2400;
break;
}
case 4800:
{
speed = B4800;
break;
}
case 9600:
{
speed = B9600;
break;
}
case 19200:
{
speed = B19200;
break;
}
case 38400:
{
speed = B38400;
break;
}
case 115200:
{
speed = B115200;
break;
}
}
cfsetispeed(&new_cfg,speed); //设置波特率
cfsetospeed(&new_cfg,speed);
//设置数据位
switch(data_bits)
{
case 7:
{
new_cfg.c_cflag|=CS7;
break;
}
case 8:
{
new_cfg.c_cflag|=CS8;
break;
}
}
//设置停止位
switch(stop_bits)
{
case 1:
{
new_cfg.c_cflag &=~CSTOPB; //设置停止位数为一位
break;
}
case 2:
{
new_cfg.c_cflag |=CSTOPB; //设置停止位数为两位
break;
}
}
//设置奇偶校验位
switch(parity)
{
case 'o':
case 'O':
{
new_cfg.c_cflag|=(PARODD|PARENB);
new_cfg.c_iflag|=(INPCK |ISTRIP);
break;
}
case 'e':
case 'E':
{
new_cfg.c_cflag |=PARENB;
new_cfg.c_cflag &=~PARODD;
new_cfg.c_iflag |=(INPCK | ISTRIP);
break;
}
case 's':
case 'S':
{
new_cfg.c_cflag &=~PARENB;
new_cfg.c_cflag &=~CSTOPB;
break;
}
case 'n':
case 'N':
{
new_cfg.c_cflag &=~PARENB; //无奇偶校验位
new_cfg.c_iflag &=~INPCK; //不进行奇偶校验
break;
}
}
new_cfg.c_cc[VTIME] =10; //VTIME定义等待的时间,单位是百毫秒
new_cfg.c_cc[VMIN] =5; //VMIN定义了要求等待的最小字节数,
// 这个字节数可能为0
//处理未接收字符
tcflush(fd,TCIFLUSH); //清空输入缓冲区
if((tcsetattr(fd,TCSANOW,&new_cfg))!=0) //应用新终端设置
{
perror("tcsetattr");
return -1;
}
return 0;
}
部分解释
- 串口设置有一个很重要的结构体termios。
这个链接有助于理解termios结构体: - 要理解原始模式。
- 做的笔记
tcgettattr用于获取终端的相关参数
tcsettattr用于设置终端参数
tcflush用于清空输入、输出缓冲区
TCIFLUSHU、TCOFLUSH和TCIOFLUSH,分别代表输入缓冲区、输出缓冲区和输入输
出缓冲区
读取数据
代码
void read_data(int fd)
{
char buffer[BUFF_SIZE],dest[1024];
char array[10]="$GPRMC";
int res,i=0,j=0,k;
int data=1,len=0;
memset(dest,0,sizeof(dest)); //清空数组
do
{
memset(buffer,0,sizeof(buffer)); //清空数组
if(res=read(fd,buffer,1)>0) //每次读一个字节
{
strcat(dest,buffer); //将字符串有效部分连接在一起
if(buffer[0]=='\n')
{
i=0;
if(strncmp(dest,array,6)==0) //比较两个字符串,相同则返回0
{
printf("%s",dest);
len=strlen(dest); //计算长度
for(k=0;k<len;k++)
{
GPS_resolve_GPRMC(dest[k]);//数据解码
}
SectionID=0;
print_info(); //打印数据
}
bzero(dest,sizeof(dest)); //将前n个字节清零
}
}
}while(1);
close(fd);
}
部分笔记
strcat函数:将两个字符串有效部分连接在一起
strncmp函数:比较两个字符串,相同则返回0
strlen函数:计算长度
解析数据
代码
void GPS_resolve_GPRMC(char data)
{
if(data==',')
{
++SectionID;
i=0;
}
else
{
switch(SectionID)
{
case 1:
GPS_DATA.GPS_time[i++]=data;
if(i==2 || i==5)
{
GPS_DATA.GPS_time[i++]=':';
}
GPS_DATA.GPS_time[8]='\0';
break;
case 2:
if(data=='A')
GPS_DATA.GPS_sv='>';
else
GPS_DATA.GPS_sv='<';
break;
case 3://3158.4608
GPS_DATA.GPS_wd[++i]=data;
GPS_DATA.GPS_wd[12]='\0';
break;
case 4:
if(data=='N')
GPS_DATA.GPS_wd[0]='N';
else if(data=='S')
GPS_DATA.GPS_wd[0]='S';
break;
case 5:
GPS_DATA.GPS_jd[++i]=data;
GPS_DATA.GPS_jd[12]='\0';
break;
case 6:
if(data=='E')
GPS_DATA.GPS_jd[0]='E';
else if(data=='W')
GPS_DATA.GPS_jd[0]='W';
break;
case 7:
GPS_DATA.GPS_speed[i++]=data;
GPS_DATA.GPS_speed[4]='\0';
break;
case 9:
GPS_DATA.GPS_date[i++]=data;
if(i==2 || i==5)
{
GPS_DATA.GPS_date[i++]='-';
}
GPS_DATA.GPS_date[8]='\0';
break;
}
}
}
笔记
无
总结
- 代码主要就这三个函数。
- 这里的读取数据的代码虽然比较长,但是经过我的测试,比一些博主的要好一点。
读取的数据比较完整。 - 也有用sscanf函数进行数据解析的,其实看个人喜好吧,功能都差不多,我比较喜欢这种明了的。