无限循环从串口接收

时间:2012-07-16 06:44:00

标签: linux serial-port

来自this我复制了串口配置示例:

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

1 个答案:

答案 0 :(得分:2)

查看您的代码

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

您已在此循环之前编写了一个数据包,然后在第一次迭代时读取了可读数据并将其读入缓冲区。每次使用memset缓冲区为零时,您需要使用调用read的返回值中给出的读取字节数来终止缓冲区。然后无限循环,每次再次读取 - 但后续读取将不再复制任何数据,因为没有可读取。但是,通过调用read来保持缓冲区不变,并且每次迭代时打印输出保持不变,因为每次迭代缓冲区保持不变。

至于阻塞方面,您应该阅读以下指南(之前已经推荐过SO,并且作为串口编程的介绍非常好)

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

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

  

VMIN指定要读取的最小字符数。如果设置了   为0,则VTIME值指定等待每个的时间   字符阅读。注意,这并不意味着对N的读取调用   bytes将等待N个字符进入。而不是超时   应用于第一个字符,读取调用将返回该数字   可立即使用的字符数(最多为您要求的数字)。

     

如果VMIN非零,则VTIME指定等待第一个的时间   字符阅读。如果在给定的时间内读取一个字符,则任何读取   将阻塞(等待)直到读取所有VMIN字符。那就是一次   读取第一个字符,串行接口驱动程序期望   接收整个字符包(总共VMIN字节)。如果不   在允许的时间内读取字符,然后调用read   返回0.此方法允许您告诉您需要的串行驱动程序   正好N个字节,任何读取调用都将返回0或N个字节。然而,   超时仅适用于第一个字符读取,因此对于某些字符   因为驱动程序错过了N字节数据包中的一个字符   读取调用可以永远阻止等待额外输入   字符。

     

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