问题
I'm currently writing a program that needs to communicate with an AT interface over an UART interface (the operating system is Linux). But I'm having trouble using select()
on the file descriptor. For some reason select does not consider the file descriptor to be ready for reading, but To narrow down the problem I have used the following program.
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;
}
The run looks something like this
root@linux:~# ./stuff
ret = 0
read: "AT
OK
"
Which indicates that select thinks that there is no data, but when trying to read there is data. This seems very strange to me. Also, I've tried to exchange the tty with stdin, and that works just fine.
The code is being run on Texas Instruments EZSDK PSP kernel, but that shouldn't be the problem. Also, the stty
settings looks like the following
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
Have I missed som crucial flag to open()
? or perhaps need to set some setting using termios
? Does this method require some special hardware
EDIT:
I get the same problem when trying to run the program /dev/ttyUSB0
, which also happens to be is an AT interface. Seems to me that it is tty
related.
changed fd to what I actually used and wondered about.
回答1:
You don't add file descriptor of serial port to fd set.
Change line:
FD_SET(0, &rfds);
to:
FD_SET(fd, &rfds);
Or add the following line, if you need fd zero in the set.
FD_SET(fd, &rfds);
回答2:
I believe it should be /dev/ttyS1 and not /dev/tty01. You are attempting to select on the VT (virtual terminal) which happens to be attached to the UART in your embedded board, but this is not the same thing,
来源:https://stackoverflow.com/questions/11986998/select-does-not-seem-to-work-on-tty