无限循环从串口接收

从这里我复制了串口configuration的例子:

tcgetattr (serialfd, &tty); cfsetospeed(&tty,B115200); cfsetispeed(&tty,B115200); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; tty.c_iflag &= ~IGNBRK; tty.c_lflag = 0; tty.c_oflag = 0; tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 5; tty.c_iflag &= ~(IXON | IXOFF | IXANY); tty.c_cflag |= (CLOCAL | CREAD); tty.c_cflag &= ~(PARENB | PARODD); tty.c_cflag |= 0; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; 

我的实际代码是这样的:

 char buf[100]; write(serialfd, "PING", strlen("PING")); fsync(serialfd); while (1) { read(serialfd, buf, sizeof(buf)); printf("length: %d\n", strlen(buf)); } 

在这种情况下,打印length: 6无限停止。 当我改变tty.c_cc[VMIN] = 1tty.c_cc[VTIME] = 0它不会读取(它阻塞在read()

我使用debian 6.0.5与USB串行转换器。 我打开这样的串口:

 serialfd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_SYNC); 

Solutions Collecting From Web of "无限循环从串口接收"

看看你的代码

 while (1) { read(serialfd, buf, sizeof(buf)); printf("length: %d\n", strlen(buf)); } 

在这个循环之前,你已经写了一个包,然后在第一次迭代中读取可用的数据,然后读入缓冲区。 您需要将您的缓冲区memset设置为零或零零终止您的缓冲区使用读取您的调用返回值中读取字节计数read 。 然后,你循环无限次,每次再次读取 – 但随后的读取将不会复制任何更多的数据,因为没有读取。 但是,由于读取调用,缓冲区保持不变,因此每次迭代时打印的输出都保持不变,因为缓冲区在每次迭代中保持不变。

至于阻塞方面,你应该阅读下面的指南(以前在SO上推荐过,作为串口编程的介绍很好)

http://www.easysw.com/~mike/serial/serial.html

本节介绍将VMIN和VTIME设置为各种值时的行为。 特别是最后一段解释你看到的阻塞行为。

VMIN指定要读取的最小字符数。 如果设置为0,则VTIME值指定等待每个字符读取的时间。 请注意,这并不意味着读取N个字节的电话​​将等待N个字符进入。相反,超时将应用于第一个字符,读取的电话将返回可立即使用的字符数(最多可达数字请求)。

如果VMIN不为零,则VTIME指定等待读取第一个字符的时间。 如果在给定的时间内读取了一个字符,任何读取都将被阻塞(等待)直到读取所有的VMIN字符。 也就是说,一旦读取了第一个字符,串行接口驱动程序就希望接收整个字符的数据包(总共VMIN字节)。 如果在允许的时间内没有读取任何字符,那么读取的调用返回0.这个方法允许你告诉串行驱动你需要正好N个字节,任何读取调用将返回0或N个字节。 但是,超时只适用于第一个字符读取,所以如果由于某种原因,驱动程序错过了N字节数据包中的一个字符,则读取的调用可能会永远阻止等待额外的输入字符。

VTIME指定十分之几秒等待传入字符的时间量。 如果VTIME设置为0(缺省值),读取将无限期地阻塞(等待),除非NDELAY选项在open或fcntl的端口上设置。