if(speed==name_arr[i]){
tcflush(fd,TCIOFLUSH);
cfsetispeed(&Opt,speed_arr[i]);
cfsetospeed(&Opt,speed_arr[i]);
status=tcsetattr(fd,TCSANOW,&Opt);
if(status!
=0){
perror("tcsetattrfd");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
3.设置串口信息
这主要包括:
数据位、停止位、奇偶校验位这些主要的信息。
/**
*@brief设置串口数据位,停止位和效验位
*@paramfd类型int打开的串口文件句柄
*@paramdatabits类型int数据位取值为7或者8
*@paramstopbits类型int停止位取值为1或者2
*@paramparity类型int效验类型取值为N,E,O,,S
*/
intset_Parity(intfd,intdatabits,intstopbits,intparity)
{
structtermiosoptions;
if(tcgetattr(fd,&options)!
=0){
perror("SetupSerial1");
return(FALSE);
}
options.c_cflag&=~CSIZE;
options.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);/*Input*/
options.c_oflag&=~OPOST;/*Output*/
switch(databits)/*设置数据位数*/
{
case7:
options.c_cflag|=CS7;
break;
case8:
options.c_cflag|=CS8;
break;
default:
fprintf(stderr,"Unsupporteddatasize\n");return(FALSE);
}
switch(parity)
{
case'n':
case'N':
options.c_cflag&=~PARENB;/*Clearparityenable*/
options.c_iflag&=~INPCK;/*Enableparitychecking*/
break;
case'o':
case'O':
options.c_cflag|=(PARODD|PARENB);/*设置为奇效验*/
options.c_iflag|=INPCK;/*Disnableparitychecking*/
break;
case'e':
case'E':
options.c_cflag|=PARENB;/*Enableparity*/
options.c_cflag&=~PARODD;/*转换为偶效验*/
options.c_iflag|=INPCK;/*Disnableparitychecking*/
break;
case'S':
case's':
/*asnoparity*/
options.c_cflag&=~PARENB;
options.c_cflag&=~CSTOPB;break;
default:
fprintf(stderr,"Unsupportedparity\n");
return(FALSE);
}
/*设置停止位*/
switch(stopbits)
{
case1:
options.c_cflag&=~CSTOPB;
break;
case2:
options.c_cflag|=CSTOPB;
break;
default:
fprintf(stderr,"Unsupportedstopbits\n");
return(FALSE);
}
/*Setinputparityoption*/
if(parity!
='n')
options.c_iflag|=INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME]=0;/*设置超时0seconds*/
options.c_cc[VMIN]=13;/*definetheminimumbytesdatatobereaded*/
if(tcsetattr(fd,TCSANOW,&options)!
=0)
{
perror("SetupSerial3");
return(FALSE);
}
return(TRUE);
}
在上述代码中,有两句话特别重要:
options.c_cc[VTIME]=0;/*设置超时0seconds*/
options.c_cc[VMIN]=13;/*definetheminimumbytesdatatobereaded*/
这两句话决定了对串口读取的函数read()的一些功能。
我将着重介绍一下他们对read()函数的影响。
对串口操作的结构体是
Struct{
tcflag_tc_iflag;/*输入模式标记*/
tcflag_tc_oflag;/*输出模式标记*/
tcflag_tc_cflag;/*控制模式标记*/
tcflag_tc_lflag;/*本地模式标记*/
cc_tc_line;/*线路规程*/
cc_tc_cc[NCCS];/*控制符号*/
};
其中cc_tc_line只有在一些特殊的系统程序(比如,设置通过tty设备来通信的网络协议)中才会用。
在数组c_cc中有两个下标(VTIME和VMIN)对应的元素不是控制符,并且只是在原始模式下有效。
只有在原始模式下,他们决定了read()函数在什么时候返回。
在标准模式下,除非设置了O_NONBLOCK选项,否则只有当遇到文件结束符或各行的字符都已经编辑完毕后才返回。
控制符VTIME和VMIN之间有着复杂的关系。
VTIME定义要求等待的零到几百毫秒的时间量(通常是一个8位的unsignedchar变量,取值不能大于cc_t)。
VMIN定义了要求等待的最小字节数(不是要求读的字节数——read()的第三个参数才是指定要求读的最大字节数),这个字节数可能是0。
l如果VTIME取0,VMIN定义了要求等待读取的最小字节数。
函数read()只有在读取了VMIN个字节的数据或者收到一个信号的时候才返回。
l如果VMIN取0,VTIME定义了即使没有数据可以读取,read()函数返回前也要等待几百毫秒的时间量。
这时,read()函数不需要像其通常情况那样要遇到一个文件结束标志才返回0。
l如果VTIME和VMIN都不取0,VTIME定义的是当接收到第一个字节的数据后开始计算等待的时间量。
如果当调用read函数时可以得到数据,计时器马上开始计时。
如果当调用read函数时还没有任何数据可读,则等接收到第一个字节的数据后,计时器开始计时。
函数read可能会在读取到VMIN个字节的数据后返回,也可能在计时完毕后返回,这主要取决于哪个条件首先实现。
不过函数至少会读取到一个字节的数据,因为计时器是在读取到第一个数据时开始计时的。
l如果VTIME和VMIN都取0,即使读取不到任何数据,函数read也会立即返回。
同时,返回值0表示read函数不需要等待文件结束标志就返回了。
这就是这两个变量对read函数的影响。
我使用的读卡器每次传送的数据是13个字节,一开始,我把它们设置成
options.c_cc[VTIME]=150
options.c_cc[VMIN]=0;
结果,每次读取的信息只有8个字节,剩下的5个字节要等到下一次打卡时才能收到。
就是由于这个原因造成的。
根据上面规则的第一条,我把VTIME取0,VMIN=13,也就是正好等于一次需要接收的字节数。
这样就实现了一次读取13个字节值。
同时,得出这样的结论,如果读卡器送出的数据为n个字节,那么就把VMIN=n,这样一次读取的信息正好为读卡器送出的信息,并且读取的时候不需要进行循环读取。
4.读取数据
有了上面的函数后,我设置了串口的基本信息,根据我们自己的实际情况,设置了相应的参数,就可以读取数据了。
voidgetcardinfo(char*buff){
intfd;
intnread,count=0;
chartempbuff[13];
char*dev="/dev/ttyS0";//串口1
fd=OpenDev(dev);
set_speed(fd,9600);
if(set_Parity(fd,8,1,'N')==FALSE){
printf("SetParityError\n");
//return-1;
}
while
(1)//循环读取数据
{
count=0;
//sleep(5000);
while
(1)
{
if((nread=read(fd,tempbuff,13))>0)
{
//printf("\nLen%d\n",nread);
memcpy(&buff[count],tempbuff,nread);
count+=nread;
}
if(count==13)
{
buff[count+1]='\0';
//printf("\n%s",buff);
break;
}
}
//break;
}
//returnbuff;
close(fd);
pthread_exit(NULL);
//close(fd);
//exit(0);
}
这是我原来的程序,其实把VMIN设置以后,可以改成:
voidgetcardinfo(char*buff){
intfd;
intnread,count=0;
chartempbuff[13];
char*dev="/dev/ttyS0";//串口1
fd=OpenDev(dev);
set_speed(fd,9600);
if(set_Parity(fd,8,1,'N')==FALSE){
printf("SetParityError\n");
//return-1;
}
nread=read(fd,buff,13)
close(fd);
}
5.程序完整代码:
#include/*标准输入输出定义*/
#include/*标准函数库定义*/
#include/*Unix标准函数定义*/
#include
#include
#include/*文件控制定义*/
#include/*PPSIX终端控制定义*/
#include/*错误号定义*/
#defineFALSE-1
#defineTRUE0
/**
*@brief设置串口通信速率
*@paramfd类型int打开串口的文件句柄
*@paramspeed类型int串口速度
*@returnvoid
*/
intspeed_arr[]={B38400,B19200,B9600,B4800,B2400,B1200,B300,
B38400,B19200,B9600,B4800,B2400,B1200,B300,};
intname_arr[]={38400,19200,9600,4800,2400,1200,300,38400,
19200,9600,4800,2400,1200,300,};
voidset_speed(intfd,intspeed){
inti;
intstatus;
structtermiosOpt;
tcgetattr(fd,&Opt);
for(i=0;iif(speed==name_arr[i]){
tcflush(fd,TCIOFLUSH);
cfsetispeed(&Opt,speed_arr[i]);
cfsetospeed(&Opt,speed_arr[i]);
status=tcsetattr(fd,TCSANOW,&Opt);
if(status!
=0){
perror("tcsetattrfd");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
/**
*@brief设置串口数据位,停止位和效验位
*@paramfd类型int打开的串口文件句柄
*@paramdatabits类型int数据位取值为7或者8
*@paramstopbits类型int停止位取值为1或者2
*@paramparity类型int效验类型取值为N,E,O,,S
*/
intset_Parity(intfd,intdatabits,intstopbits,intparity)
{
structtermiosoptions;
if(tcgetattr(fd,&options)!
=0){
perror("SetupSerial1");
return(FALSE);
}
options.c_cflag&=~CSIZE;
options.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);/*Input*/
options.c_oflag&=~OPOST;/*Output*/
switch(databits)/*设置数据位数*/
{
case7:
options.c_cflag|=CS7;
break;
case8:
options.c_cflag|=CS8;
break;
default:
fprintf(stderr,"Unsupporteddatasize\n");return(FALSE);
}
switch(parity)
{
case'n':
case'N':
options.c_cflag&=~PARENB;/*Clearparityenable*/
options.c_iflag&=~INPCK;/*Enableparitychecking*/
break;
case'o':
case'O':
options.c_cflag|=(PARODD|PARENB);/*设置为奇效验*/
options.c_iflag|=INPCK;/*Disnableparitychecking*/
break;
case'e':
case'E':
options.c_cflag|=PARENB;/*Enableparity*/
options.c_cflag&=~PARODD;/*转换为偶效验*/
options.c_iflag|=INPCK;/*Disnableparitychecking*/
break;
case'S':
case's':
/*asnoparity*/
options.c_cflag&=~PARENB;
options.c_cflag&=~CSTOPB;break;
default:
fprintf(stderr,"Unsupportedparity\n");
return(FALSE);
}
/*设置停止位*/
switch(stopbits)
{
case1:
options.c_cflag&=~CSTOPB;
break;
case2:
options.c_cflag|=CSTOPB;
break;
default:
fprintf(stderr,"Unsupportedstopbits\n");
return(FALSE);
}
/*Setinputparityoption*/
if(parity!
='n')
options.c_iflag|=INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME]=0;/*设置超时15seconds*/
options.c_cc[VMIN]=13;/*definetheminimumbytesdatatobereaded*/
if(tcsetattr(fd,TCSANOW,&options)!
=0)
{
perror("SetupSerial3");
return(FALSE);
}
return(TRUE);
}
本文来自CSDN博客,转载请标明出处: