我目前正在编写一个需要通过UART接口与AT接口通信的程序(操作系统是Linux)。但我在文件描述符上使用select()
时遇到问题。由于某种原因,select不会认为文件描述符已准备好进行读取,但为了缩小问题,我使用了以下程序。
int main()
{
char buffer[BSIZE];
fd_set rfds;
int ret;
struct termios cnf;
struct timeval tv;
fd = open("/dev/ttyO1", O_RDWR);
// Have also tried to set fd = 0 for stdin, as a reference
signal(SIGINT, sig_handler);
tcgetattr(fd, &cnf);
old = cnf;
cfmakeraw(&cnf);
tcsetattr(fd, TCSANOW, &cnf);
while (1) {
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
write(fd, "AT\r", 3);
ret = select(fd+1, &rfds, NULL, NULL, &tv);
printf("ret = %d\n", ret);
if (ret < 0) {
perror("select()");
}
else {
ret = read(fd, buffer, BSIZE-1);
buffer[ret] = '\0';
printf("read: \"%s\"\n", buffer);
}
}
return 0;
}
运行看起来像这样
root@linux:~# ./stuff
ret = 0
read: "AT
OK
"
表示select认为没有数据,但在尝试读取时有数据。这对我来说似乎很奇怪。此外,我试图用stdin交换tty,这很好用。
代码正在德州仪器EZSDK PSP内核上运行,但这应该不是问题。此外,stty
设置如下所示
root@linux:~# stty -aF /dev/ttyO1
speed 9600 baud; rows 24; columns 80;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
我是否错过了open()
的关键旗帜?或者可能需要使用termios
设置一些设置?这种方法是否需要一些特殊的硬件
编辑:
尝试运行程序/dev/ttyUSB0
时遇到同样的问题,这也恰好是AT接口。在我看来它是tty
相关的。
将fd更改为我实际使用和想知道的内容。
答案 0 :(得分:4)
您不要将串口的文件描述符添加到fd set。
更改行:
FD_SET(0, &rfds);
为:
FD_SET(fd, &rfds);
如果您需要在集合中使用fd零,请添加以下行。
FD_SET(fd, &rfds);
答案 1 :(得分:0)
我认为它应该是/ dev / ttyS1而不是/ dev / tty01。您试图在VT(虚拟终端)上选择碰巧连接到嵌入式主板上的UART,但这不是一回事,