我有一个串行到 USB 转换器(FTDI,从http://www.ftdichip.com/Drivers/VCP.htm安装的驱动程序)将串行设备连接到 MacBook Air。它在 MacBook 上显示为/dev/cu.usbserial-A4017CQY
和/dev/tty.usbserial-A4017CQY
。无论我使用这两个中的哪一个,我描述的所有行为都是相同的。
编辑:使用/dev/cu.*
确实解决了问题。我不确定为什么当我第一次发布这个问题时它似乎不起作用。感谢duskwuff 为我指明了正确的方向,尽管他的TTY 名称倒过来了:/dev/tty.*
将等待流量控制,而/dev/cu.*
不会。
open()
我遇到的第一个问题是,如果我不使用该O_NONBLOCK
标志,系统调用将永远阻塞。使用该标志,我得到了一个很好的文件描述符,但write()
似乎并没有真正写入(尽管它返回很好,声称已写入字节),并且read()
失败并出现错误“资源暂时不可用”。
stty -af /dev/cu.usbserial-A4017CQY
显示设置就好了,但是如果我尝试使用类似的命令更改它们,stty -f /dev/cu.usbserial-A4017CQY -clocal
当连续调用stty
.
如果我select()
在读/写之前等待设备准备好,它会在短时间内报告它已准备好写入,但永远不会读取。这与如何write()
毫无怨言地完成,而read()
失败。请注意,写入的数据从未真正进入设备。
我为调试而编写的整个测试程序如下:
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/select.h>
#define SYSCALL(A) do { ret = A; if (ret == -1) { perror(#A); return -1; } else printf("%s returned %d\n", #A, ret); } while (0)
int ret; /* necessary for SYSCALL */
int main()
{
struct termios tio;
char buf[256];
int fd = open("/dev/cu.usbserial-A4017CQY",
O_RDWR | O_NOCTTY | O_NONBLOCK);
fd_set rfds, wfds, xfds;
struct timeval to;
to.tv_sec = 5;
to.tv_usec = 0;
SYSCALL(tcgetattr(fd, &tio));
cfmakeraw(&tio);
tio.c_cflag = CS8|CREAD|CLOCAL;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 1;
cfsetispeed(&tio, B115200);
cfsetospeed(&tio, B115200);
SYSCALL(tcsetattr(fd, TCSANOW, &tio));
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&xfds);
FD_SET(fd, &rfds);
FD_SET(fd, &wfds);
FD_SET(fd, &xfds);
int ret = select(fd+1, &rfds, NULL, &xfds, &to);
if (ret == -1) perror("select");
else if (ret > 0)
{
if(FD_ISSET(fd, &rfds))
puts("Ready to read");
if(FD_ISSET(fd, &wfds))
puts("Ready to write");
if(FD_ISSET(fd, &xfds))
puts("Exception!");
}
else puts("Timed out!");
SYSCALL(write(fd, "/home\n", 5));
SYSCALL(read(fd, buf, 256));
return 0;
}