来自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] = 1
和tty.c_cc[VTIME] = 0
时,它无法读取。(它会在read()
中阻止)
我正在使用debian 6.0.5和usb到串口转换器。我打开这样的串口:
serialfd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_SYNC);
答案 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。