有兩個可以進行控制串口阻塞性(同時控制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 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 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 阻塞:fcntl(fd,F_SETFL,0) [cpp] view plain copy 非阻塞:fcntl(fd,F_SETFL,FNDELAY)