linux下串口的阻塞和非阻塞操作
2017-07-22 11:15
495 查看
有两个可以进行控制串口阻塞性(同时控制read和write):一个是在打开串口的时候,open函数是否带O_NDELAY;第二个是可以在打开串口之后通过fcntl()函数进行控制。
阻塞的定义:
对于read,block指当串口输入缓冲区没有数据的时候,read函数将会阻塞在这里,移植到串口输入缓冲区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数;
对于write,block指当串口输出缓冲区满,或剩下的空间小于将要写入的字节数,则write将阻塞,一直到串口输出缓冲区中剩下的空间大于等于将要写入的字节数,执行写入操作,返回写入的字节数。
非阻塞的定义:
对于read,no block指当串口输入缓冲区没有数据的时候,read函数立即返回,返回值为0。
对于write,no block指当串口输出缓冲区满,或剩下的空间小于将要写入的字节数,则write将进行写操作,写入当前串口输出缓冲区剩下空间允许的字节数,然后返回写入的字节数。
[cpp]
view plain
copy
print?
static int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio;
struct termios oldtio;
if(tcgetattr(fd,&oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero(&newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL |CREAD;
newtio.c_cflag &= ~CSIZE;
/***********数据位选择****************/
switch(nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
/***********校验位选择****************/
switch(nEvent)
{
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
f5f6
newtio.c_iflag |= (INPCK |ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
/***********波特率选择****************/
switch(nSpeed)
{
case 2400:
cfsetispeed(&newtio,B2400);
cfsetospeed(&newtio,B2400);
break;
case 4800:
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
case 57600:
cfsetispeed(&newtio,B57600);
cfsetospeed(&newtio,B57600);
break;
case 115200:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;
case 460800:
cfsetispeed(&newtio,B460800);
cfsetospeed(&newtio,B460800);
break;
default:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
/***********停止位选择****************/
if(nStop == 1){
newtio.c_cflag &= ~CSTOPB;
}
else if(nStop ==2){
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = FRAME_MAXSIZE; //阻塞条件下有效
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio)) != 0)
{
perror("com set error");
return -1;
}
printf("set done!\n");
return 0;
}
[cpp]
view plain
copy
print?
static int open_port(int fd,int comport)
{
/***********打开串口1****************/
if(comport == 1)
{
fd = open("/dev/ttyAT1",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1){
perror("Can't Open Serial Port");
return -1;
}
}
/***********打开串口2****************/
else if(comport == 2)
{
fd = open("/dev/ttyAT2",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1){
perror("Can't Open Serial Port");
return -1;
}
}
/***********打开串口3****************/
else if(comport == 3)
{
fd = open("/dev/ttyAT3",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1){
perror("Can't Open Serial Port");
return -1;
}
}
if(comport == 1)
{
if(fcntl(fd,F_SETFL,FNDELAY) < 0)//非阻塞,覆盖前面open的属性
{
printf("fcntl failed\n");
}
else{
printf("fcntl=%d\n",fcntl(fd,F_SETFL,FNDELAY));
}
}
else
{
if(fcntl(fd,F_SETFL,0) < 0){ //阻塞,即使前面在open串口设备时设置的是非阻塞的,这里设为阻塞后,以此为准
printf("fcntl failed\n");
}
else{
printf("fcntl=%d\n",fcntl(fd,F_SETFL,0));
}
}
if(isatty(STDIN_FILENO) == 0){
printf("standard input is not a terminal device\n");
}
else{
printf("isatty sucess!\n");
}
printf("fd-open=%d\n",fd);
return fd;
}
所以,Linux的串口的阻塞性通过fcntl()函数进行设置即可。
[cpp]
view plain
copy
print?
阻塞:fcntl(fd,F_SETFL,0)
[cpp]
view plain
copy
print?
非阻塞:fcntl(fd,F_SETFL,FNDELAY)
from:http://blog.csdn.net/wuhengwudi/article/details/7454629
阻塞的定义:
对于read,block指当串口输入缓冲区没有数据的时候,read函数将会阻塞在这里,移植到串口输入缓冲区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数;
对于write,block指当串口输出缓冲区满,或剩下的空间小于将要写入的字节数,则write将阻塞,一直到串口输出缓冲区中剩下的空间大于等于将要写入的字节数,执行写入操作,返回写入的字节数。
非阻塞的定义:
对于read,no block指当串口输入缓冲区没有数据的时候,read函数立即返回,返回值为0。
对于write,no block指当串口输出缓冲区满,或剩下的空间小于将要写入的字节数,则write将进行写操作,写入当前串口输出缓冲区剩下空间允许的字节数,然后返回写入的字节数。
[cpp]
view plain
copy
print?
static int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio;
struct termios oldtio;
if(tcgetattr(fd,&oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero(&newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL |CREAD;
newtio.c_cflag &= ~CSIZE;
/***********数据位选择****************/
switch(nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
/***********校验位选择****************/
switch(nEvent)
{
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
f5f6
newtio.c_iflag |= (INPCK |ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
/***********波特率选择****************/
switch(nSpeed)
{
case 2400:
cfsetispeed(&newtio,B2400);
cfsetospeed(&newtio,B2400);
break;
case 4800:
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
case 57600:
cfsetispeed(&newtio,B57600);
cfsetospeed(&newtio,B57600);
break;
case 115200:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;
case 460800:
cfsetispeed(&newtio,B460800);
cfsetospeed(&newtio,B460800);
break;
default:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
/***********停止位选择****************/
if(nStop == 1){
newtio.c_cflag &= ~CSTOPB;
}
else if(nStop ==2){
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = FRAME_MAXSIZE; //阻塞条件下有效
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio)) != 0)
{
perror("com set error");
return -1;
}
printf("set done!\n");
return 0;
}
static int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio; struct termios oldtio; if(tcgetattr(fd,&oldtio) != 0) { perror("SetupSerial 1"); return -1; } bzero(&newtio,sizeof(newtio)); newtio.c_cflag |= CLOCAL |CREAD; newtio.c_cflag &= ~CSIZE; /***********数据位选择****************/ switch(nBits) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } /***********校验位选择****************/ switch(nEvent) { case 'O': newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'E': newtio.c_iflag |= (INPCK |ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'N': newtio.c_cflag &= ~PARENB; break; } /***********波特率选择****************/ switch(nSpeed) { case 2400: cfsetispeed(&newtio,B2400); cfsetospeed(&newtio,B2400); break; case 4800: cfsetispeed(&newtio,B4800); cfsetospeed(&newtio,B4800); break; case 9600: cfsetispeed(&newtio,B9600); cfsetospeed(&newtio,B9600); break; case 57600: cfsetispeed(&newtio,B57600); cfsetospeed(&newtio,B57600); break; case 115200: cfsetispeed(&newtio,B115200); cfsetospeed(&newtio,B115200); break; case 460800: cfsetispeed(&newtio,B460800); cfsetospeed(&newtio,B460800); break; default: cfsetispeed(&newtio,B9600); cfsetospeed(&newtio,B9600); break; } /***********停止位选择****************/ if(nStop == 1){ newtio.c_cflag &= ~CSTOPB; } else if(nStop ==2){ newtio.c_cflag |= CSTOPB; } newtio.c_cc[VTIME] = 1; newtio.c_cc[VMIN] = FRAME_MAXSIZE; //阻塞条件下有效 tcflush(fd,TCIFLUSH); if((tcsetattr(fd,TCSANOW,&newtio)) != 0) { perror("com set error"); return -1; } printf("set done!\n"); return 0; }
[cpp]
view plain
copy
print?
static int open_port(int fd,int comport)
{
/***********打开串口1****************/
if(comport == 1)
{
fd = open("/dev/ttyAT1",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1){
perror("Can't Open Serial Port");
return -1;
}
}
/***********打开串口2****************/
else if(comport == 2)
{
fd = open("/dev/ttyAT2",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1){
perror("Can't Open Serial Port");
return -1;
}
}
/***********打开串口3****************/
else if(comport == 3)
{
fd = open("/dev/ttyAT3",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1){
perror("Can't Open Serial Port");
return -1;
}
}
if(comport == 1)
{
if(fcntl(fd,F_SETFL,FNDELAY) < 0)//非阻塞,覆盖前面open的属性
{
printf("fcntl failed\n");
}
else{
printf("fcntl=%d\n",fcntl(fd,F_SETFL,FNDELAY));
}
}
else
{
if(fcntl(fd,F_SETFL,0) < 0){ //阻塞,即使前面在open串口设备时设置的是非阻塞的,这里设为阻塞后,以此为准
printf("fcntl failed\n");
}
else{
printf("fcntl=%d\n",fcntl(fd,F_SETFL,0));
}
}
if(isatty(STDIN_FILENO) == 0){
printf("standard input is not a terminal device\n");
}
else{
printf("isatty sucess!\n");
}
printf("fd-open=%d\n",fd);
return fd;
}
static int open_port(int fd,int comport) { /***********打开串口1****************/ if(comport == 1) { fd = open("/dev/ttyAT1",O_RDWR|O_NOCTTY|O_NDELAY); if(fd == -1){ perror("Can't Open Serial Port"); return -1; } } /***********打开串口2****************/ else if(comport == 2) { fd = open("/dev/ttyAT2",O_RDWR|O_NOCTTY|O_NDELAY); if(fd == -1){ perror("Can't Open Serial Port"); return -1; } } /***********打开串口3****************/ else if(comport == 3) { fd = open("/dev/ttyAT3",O_RDWR|O_NOCTTY|O_NDELAY); if(fd == -1){ perror("Can't Open Serial Port"); return -1; } } if(comport == 1) { if(fcntl(fd,F_SETFL,FNDELAY) < 0)//非阻塞,覆盖前面open的属性 { printf("fcntl failed\n"); } else{ printf("fcntl=%d\n",fcntl(fd,F_SETFL,FNDELAY)); } } else { if(fcntl(fd,F_SETFL,0) < 0){ //阻塞,即使前面在open串口设备时设置的是非阻塞的,这里设为阻塞后,以此为准 printf("fcntl failed\n"); } else{ printf("fcntl=%d\n",fcntl(fd,F_SETFL,0)); } } if(isatty(STDIN_FILENO) == 0){ printf("standard input is not a terminal device\n"); } else{ printf("isatty sucess!\n"); } printf("fd-open=%d\n",fd); return fd; }
所以,Linux的串口的阻塞性通过fcntl()函数进行设置即可。
[cpp]
view plain
copy
print?
阻塞:fcntl(fd,F_SETFL,0)
阻塞:fcntl(fd,F_SETFL,0)
[cpp]
view plain
copy
print?
非阻塞:fcntl(fd,F_SETFL,FNDELAY)
from:http://blog.csdn.net/wuhengwudi/article/details/7454629
相关文章推荐
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux串口阻塞与非阻塞控制
- linux 等待队列 与linux 等待队列头关系-不懂linux驱动阻塞操作可以看看
- Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]
- Linux 文件操作中的阻塞和非阻塞操作
- linux下串口协议控制51单片机(涉及多线程操作)
- linux嵌入式开发中,由串口日志中需要输入选择而导致的系统阻塞处理方法
- linux串口操作及设置详解
- Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]【转】
- LINUX 下qt 操作串口
- 自己写的Linux下的串口操作
- linux串口操作及设置详解
- linux下的串口操作
- linux串口操作及设置详解
- linux串口操作及设置详解