Linux串行读取块minicom

时间:2017-01-25 01:06:33

标签: c++ linux serial-port termios

我试图从BeagleBone Black上的串口(/dev/ttyS4)读取,但我认为(?)这应该适用于所有Linux设备。

目前,我可以设置波特率为9600的minicom和8N1数据,以便正确读取串口。但是,如果我尝试直接cat /dev/ttyS4,我的终端中就不会显示任何内容。我的代码也执行此操作,并返回Resource temporarily unavailable错误,我怀疑这是cat命令发生的事情。

如果我运行stty -F /dev/ttyS4,我会得到以下输出(据我所知,这与我的minicom设置一致):

speed 9600 baud; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>; start = <undef>; stop = <undef>; susp = <undef>; rprnt = <undef>; werase = <undef>; lnext = <undef>; flush = <undef>;
-brkint -imaxbel
-opost -onclr
-isig -iexten -echo -echoe -echok -echoctl -echoke

一个有趣的注意事项是,当我minicom打开时,如果我启动我的程序,minicom将停止打印任何内容,即使我停止我的程序也会保持这种状态。我需要再次打开序列设置(Ctrl-AP)并关闭它以使minicom恢复工作(似乎没有任何更改)。

我的代码如下:

int main() {
    std::cout << "Starting..." << std::endl;

    std::cout << "Connecting..." << std::endl;
    int tty4 = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);
    if (tty4 < 0) {
        std::cout << "Error opening serial terminal." << std::endl;
    }

    std::cout << "Configuring..." << std::endl;
    struct termios oldtio, newtio;
    tcgetattr(tty4, &oldtio);   // save current serial port settings
    bzero(&newtio, sizeof(newtio)); // clear struct for new settings

    newtio.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
    newtio.c_iflag = IGNPAR | ICRNL;
    newtio.c_oflag = 0;
    newtio.c_lflag = ICANON;

    tcflush(tty4, TCIFLUSH);
    tcsetattr(tty4, TCSANOW, &newtio);

    std::cout << "Reading..." << std::endl;
    while (true) {
        uint8_t byte;
        int status = read(tty4, &byte, 1);
        if (status > 0) {
            std::cout << (char)byte;
        } else if (status == -1) {
            std::cout << "\tERROR: " << strerror(errno) << std::endl;
        }
    }

    tcsetattr(tty4, TCSANOW, &oldtio);
    close(tty4);
}

编辑:通过遵循Adafruit的教程,使用BeagleBone的python,我已经让串口正常工作(在python中)。在这一点上,我确定我&#39; 做错了什么;问题是什么。我更喜欢使用C ++而不是python,因此能够很好地实现它。

1 个答案:

答案 0 :(得分:1)

您的程序以非阻塞模式打开串行终端。

   int tty4 = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);

非阻塞I / O,尤其是读取操作,需要在程序中进行额外的特殊处理。 由于您忽略了提及此模式,并且您的程序无法正确处理此模式,因此可能会将此视为错误。

open()调用中删除 O_NDELAY 选项,或插入fcntl(tty4, F_SETFL, 0)语句以恢复为阻止模式。

  

我的代码也执行此操作,并返回Resource temporarily unavailable错误,

这是一个EAGAIN错误,与非阻止读取()一致。
手册页描述了当&#34;文件描述符...被标记为非阻塞(O_NONBLOCK)时,将发生此错误,并且读取将阻止&#34;。
读取()系统调用&#34;会阻止&#34;因为没有数据来满足读取请求。

如果您坚持使用非阻塞模式,那么您的程序必须能够应对这种情况,这不是错误,而是临时/暂时状态。
但是,对于多任务系统中的典型程序,阻塞模式是更简单和优选的操作模式 您的程序应该如前所述进行修改。

串行终端的初始化存在许多问题。

   tcgetattr(tty4, &oldtio);   // save current serial port settings

永远不会检查 tcgetattr() tcsetattr()系统调用的返回值是否有错误。

   bzero(&newtio, sizeof(newtio)); // clear struct for new settings

从空的termios结构开始几乎总是一个坏主意。它似乎适用于某些系统,但它不是可移植的代码 初始化termios结构的正确方法是使用 tcgetattr()中的值。
Setting Terminal Modes Properly
由于它已被调用,因此您需要newtio = oldtio来复制结构。

    newtio.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
    newtio.c_iflag = IGNPAR | ICRNL;
    newtio.c_oflag = 0;
    newtio.c_lflag = ICANON;

更改这些标志的正确方法是启用或禁用各个属性,而不是分配常量 以下内容应该足以满足规范模式:

    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    newtio.c_cflag |= CS8;         /* 8-bit characters */
    newtio.c_cflag &= ~PARENB;     /* no parity bit */
    newtio.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    newtio.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

    newtio.c_lflag |= ICANON | ISIG;  /* canonical input */
    newtio.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);

    newtio.c_iflag &= ~INPCK;
    newtio.c_iflag |= ICRNL;
    newtio.c_iflag &= ~(INLCR | IGNCR | IUCLC | IMAXBEL);
    newtio.c_iflag &= ~(IXON | IXOFF | IXANY);   /* no SW flowcontrol */

    newtio.c_oflag &= ~OPOST;

以下是设置波特率的首选方法:

    cfsetospeed(&newtio, B9600);
    cfsetispeed(&newtio, B9600);

如果未指定任何显着属性,则使用现有设置 这可能导致不稳定的程序行为,例如有时它有效,有时它不会。

  

一个有趣的注意事项是,当我打开minicom时,如果我启动我的程序,minicom将停止打印任何内容,即使我停止我的程序也会保持这种状态。我需要再次打开串行设置(Ctrl-A,P)并关闭它以便minicom恢复工作(似乎没有任何改变)。

串行终端不适用于多个进程之间的共享 某些termios属性必须在串行设备驱动程序中实现,该驱动程序没有共享端口的概念。最新的termios属性对设备有效 在 minicom 启动后执行程序时,您正在破坏 minicom 期望执行的termios属性。
您正在使用其菜单将termios属性恢复为 minicom 的要求。