您的位置:首页 > 运维架构 > Linux

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;     
}     

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: