【问题标题】:Programming pseudo terminals communication by termios. Parity bit option doesn't works通过 termios 编程伪终端通信。奇偶校验位选项不起作用
【发布时间】:2016-09-18 13:46:04
【问题描述】:

我需要使用串口进行聊天。我通过 socat 模拟 pty:

socat -d -d PTY PTY

接下来我写了一个小演示。这就是我初始化 termios 结构的方式:

    int tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);
    struct termios tio;
    bzero(&tio, sizeof(tio));
    // Frame bus runs at 38,400 BAUD
    const int BAUD_Rate = B38400;

    cfsetispeed(&tio, BAUD_Rate);
    cfsetospeed(&tio, BAUD_Rate);

    // Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
    cfmakeraw(&tio);

    // Ignore modem lines and enable receiver and set bit per byte
    tio.c_cflag |= CLOCAL | CREAD | CS8;

    // NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
    tio.c_cflag |=  PARENB;         // Enable even parity generation
    tio.c_iflag |=  INPCK;          // Enable parity checking
    tio.c_iflag |=  PARMRK;         // Enable in-band marking 
    tio.c_iflag &= ~IGNPAR;         // Make sure input parity errors are not ignored
    if (is_odd) 
            tio.c_cflag |= PARODD;
    tcsetattr(tty_fd, TCSANOW, &tio);

接下来是我的整个演示清单:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h> 

struct termios init(int);

int main(int argc,char** argv)
{
        struct termios tio;
        char c = 0;
        int tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);

        tio = init(strcmp(argv[3], "odd"));

        if (tcsetattr(tty_fd, TCSANOW, &tio) == -1)
        {
                printf("Failed to setup the port");
                return -1;
        }

        if (strcmp(argv[2], "write") == 0)
        {
                while (c != 'q')
                {
                        scanf("%c", &c);
                        write(tty_fd, &c, 1);
                }
        }
        if (strcmp(argv[2], "read") == 0)
        {
                while (c != 'q')
                {
                        if (read(tty_fd, &c, 1) > 0)
                                printf("%c", c);
                }
        }
        close(tty_fd);
}

struct termios init(int is_odd)
{
        struct termios tio;
        bzero(&tio, sizeof(tio));
        // Frame bus runs at 38,400 BAUD
        const int BAUD_Rate = B38400;

        cfsetispeed(&tio, BAUD_Rate);
        cfsetospeed(&tio, BAUD_Rate);

        // Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
        cfmakeraw(&tio);

        // Ignore modem lines and enable receiver and set bit per byte
        tio.c_cflag |= CLOCAL | CREAD | CS8;

        // NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
        tio.c_cflag |=  PARENB;         // Enable even parity generation
        tio.c_iflag |=  INPCK;          // Enable parity checking
        tio.c_iflag |=  PARMRK;         // Enable in-band marking 
        tio.c_iflag &= ~IGNPAR;         // Make sure input parity errors are not ignored
        if (is_odd == 0) 
                tio.c_cflag |= PARODD;
        return tio;
}

当我启动一个应用程序作为读取器,另一个作为具有相似奇偶校验的写入器时,一切正常。但是当我尝试测试奇偶校验位设置时,我以不同的方式启动它们,一切正常。所有消息都发送没有任何错误。
那是因为使用了伪终端,而不是真正的 COM 端口吗?
或者也许是我创建 pty 的方式?

我的伙伴也尝试使用 python 进行类似的测试,结果也类似。我使用 Linux Mint 17.3。

感谢您的重播。

【问题讨论】:

  • 除了可能没有为驱动程序实现奇偶校验(因此被忽略)之外,init((strcmp(argv[3], "odd") == 1); 行是不正确的。 init(strcmp(argv[3], "odd") != 0); 可能是你想要的
  • 不,如果参数相等,strcmp 返回零。
  • 我知道。但是,正如您在代码中所假设的那样,在任何其他情况下都不能保证完全返回 1
  • 哦,对不起。发布此内容时,我没有看到。
  • 你一定来自Java世界。

标签: c serial-port termios socat


【解决方案1】:

我已阅读 pty 的手册页,发现伪终端根本不支持 termios 的 c_cflag 标志。

【讨论】:

  • 你在哪里找到的?我在man pty 上看不到这个。
  • @shycha 我明确地发现了here
猜你喜欢
  • 2014-05-01
  • 2015-01-10
  • 2015-12-03
  • 2012-07-02
  • 2015-06-29
  • 1970-01-01
  • 2015-04-04
  • 2011-12-08
相关资源
最近更新 更多