c - select() 似乎不适用于 TTY

标签 c linux embedded serial-port

我目前正在编写一个程序,需要通过UART接口(interface)(操作系统是Linux)与AT接口(interface)通信。但是我在文件描述符上使用 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,效果很好。

代码正在 Texas Instruments 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 接口(interface)。在我看来,它与 tty 相关。

将 fd 更改为我实际使用和想知道的内容。

最佳答案

串口的文件描述符不要添加到fd集合中。

换行:

FD_SET(0, &rfds);

到:

FD_SET(fd, &rfds);

如果你需要集合中的 fd 零,或者添加以下行。

FD_SET(fd, &rfds);

关于c - select() 似乎不适用于 TTY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11986998/

相关文章:

ARM 的 C++ 异常处理 - 通用异常处理表条目的格式

c++ - freemodbus eMBRegCoilsCB 函数体示例

python - 如何使用树莓派 PREEMPT_RT 补丁让进程实时运行?

有人可以解释一下这个函数的输出是如何获得的吗?

linux - 参数没有传递好

linux - 在 Linux 终端中运行 ffmpeg

c - 文件 link(device,socket)/dev/fd/need avoid links transition 的 Linux C 问题

c - 如何使用嵌入式 C 启动 ARM Cortex 编程?

在 C 编程中使用等号比较字符串

我可以在同一个字符串上多次调用 scanf 吗?