Linux串口阻塞与非阻塞

Linux串口编程的阻塞与否可以在open函数中设置,例如:

打开时使用:
fd = open(USAR1, O_RDWR | O_NOCTTY );//阻塞式读写


fd = open("/dev/ttyAT2",O_RDWR|O_NOCTTY|O_NDELAY);   //非阻塞读写

除了用open函数之外还可以在open函数之后用fcntl函数来设置,代码如下:

打开后使用fcntl函数修改:
fcntl(fd, F_SETFL, 0); //设为阻塞,即使前面在open串口设备时设置的是非阻塞的,这里设为阻塞后,以此为准
fcntl(fd,F_SETFL,FNDELAY)//设为非阻塞,道理同上

阻塞式读写可设置以下两参数:

opt.c_cc[VMIN] = vmin;   //设置非规范模式下的超时时长和最小字符数:阻塞模式起作用
opt.c_cc[VTIME] = vtime; //VTIME与VMIN配合使用,是指限定的传输或等待的最长时间

若 VMIN = 0 ,VTIME = 0  ,函数read未读到任何参数也立即返回,相当于非阻塞模式;

若 VMIN = 0,   VTIME > 0  ,函数read读取到数据立即返回,若无数据则等待VTIME时间返回;

若 VMIN > 0,   VTIME = 0  ,函数read()只有在读取到VMIN个字节的数据或者收到一个信号的时候才返回;

若 VMIN > 0,   VTIME > 0  ,从read读取第一个字节的数据时开始计时,并会在读取到VMIN个字节或者VTIME时间后返回。

 

例如,我在open函数设置为阻塞,并规定要接收到10字节后才返回read函数,设置代码如下:

int fd_uart;
char *uart3 = "/dev/ttySAC3";


if((fd_uart = open(uart3, O_RDWR|O_NOCTTY))<0)
		printf("open %s is failed",uart3);
	else{
		    set_opt(fd_uart, 115200, 8, 'N', 1);
        }



int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	//读出原来的配置信息,按理说之所以读出来,是有部分数据不需要改,但感觉这里是这里对新的结构体配置,也没用到读出来的值
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 	
		perror("SetupSerial 1");
		return -1;
	}
	bzero( &newtio, sizeof( newtio ) );		//新结构体清0
	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 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]  = 0;
		newtio.c_cc[VMIN] = 10;			//设置阻塞的最小字节数,阻塞条件下有效
	/*处理未接收字符*/ 
		tcflush(fd,TCIFLUSH);
	/*激活新配置*/
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	
	//	printf("set done!\n\r");
	return 0;
}

参考文章:

https://blog.csdn.net/m0_38096844/article/details/90716182

https://blog.csdn.net/wuhengwudi/article/details/7454629

你可能感兴趣的:(嵌入式)