本文介绍了如何在C或Python中实时读取多个串口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要读取多个(至少 2 个)串口(目前是通过 USB 连接的 FT2232H 模块上的两个端口).

I need to read multiple (at least 2) serial ports (currently two ports on a FT2232H module connected through USB).

我用它来监控串行连接,所以两个端口的 RX 并联连接到我需要监控的串行的 RX 和 TX.

I am using it to monitor a serial connections, so the two ports have their RX connected in parallel to RX and TX of the serial I need to monitor.

设置与这个非常相似.

我正在设置这样的端口:

I am setting up ports like this:

#define waitTime   0

int start_dev(const int speed, const char *dev) {
    int fd = open(dev, O_RDWR | O_NOCTTY |O_NONBLOCK| O_NDELAY);
    int isBlockingMode, parity = 0;
    struct termios tty;

    isBlockingMode = 0;
    if (waitTime < 0 || waitTime > 255)
        isBlockingMode = 1;

    memset (&tty, 0, sizeof tty);
    if (tcgetattr (fd, &tty) != 0) {
        /* save current serial port settings */
        printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
        exit(1);
    }

    cfsetospeed (&tty, speed);
    cfsetispeed (&tty, speed);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    tty.c_iflag &= ~IGNBRK;         // disable break processing
    tty.c_lflag = 0;                // no signaling chars, no echo,
                                    // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN]  = (1 == isBlockingMode) ? 1 : 0;            // read doesn't block
    tty.c_cc[VTIME] = (1 == isBlockingMode) ? 0 : waitTime;     // in unit of 100 milli-sec for set timeout value

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);        // ignore modem controls,
                                            // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= parity;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr (fd, TCSANOW, &tty) != 0) {
        printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
        exit(1);
    }
    return fd;
}

...和目前我有这个代码来阅读(我也试过select()):

... and currently I have this code for reading (I also tried with select()):

...
    for (running=1; running;) {
        for (int*p=devs; p<end; p++) {
            char b[256];
            int n = read(*p, b, sizeof(b));
            if (n > 0) {
                for (int i=0; i<n; i++) {
                    ...
                }
            }
        }
    }
...

这显然是非常次优的,因为它不会暂停等待字符.

This is obviously highly suboptimal because it doesn't suspend waiting for chars.

问题是我遇到了某种缓冲,因为当两个进程在一个紧密循环中交换数据时,我经常看到几个请求在一起,然后是相应的答案(1b6f 是请求,19 是空答案):

Problem is I experience some kind of buffering because when two processes exchange data on a tight loop I often see a few requests together and then the corresponding answers (1b6f is request and 19 is the empty answer):

1b6f
19
1b6f
19
1b6f
19
1b6f
191919
1b6f1b6f1b6f
19191919
1b6f1b6f1b6f1b6f
1b6f1b6f1b6f
191919

我也尝试过使用 python (pyserial),但我得到了类似的结果.

I also tried using python (pyserial), but I get similar results.

我应该如何继续以确保执行正确的时间安排?

How should I proceed to ensure correct timings are enforced?

注意:我对精确时间不太感兴趣,但应该保留序列(即:我希望避免在请求之前看到答案).

Note: I am not very interested in precise timing, but sequence should be preserved (i.e.: I would like to avoid seeing an answer before the request).

推荐答案

在我看来,如果我正确理解了一种端口嗅探器来识别串行链接上交换的事务,那么我认为您正在尝试做使用 USB 到串行转换器和传统操作系统是可行的,除非您以低波特率运行.

In my opinion what you're trying to do, which is if I understood correctly a kind of port sniffer to identify the transactions exchanged on a serial link is not feasible with USB-to-serial converters and a conventional OS, unless you're running at slow baudrates.

USB 端口总是会引入一定的延迟(可能是几十毫秒),您必须将操作系统的不可预测性放在首位.

The USB port will always introduce a certain latency (probably tens of milliseconds), and you'll have to put the unpredictability of the OS on top of that.

由于您有两个端口,您可以尝试运行两个单独的线程并为收到的每个数据块添加时间戳.这可能有助于改善情况,但我不确定它是否能让您清楚地遵循顺序.

Since you have two ports you could try to run two separate threads and timestamp each chunk of data received. That might help improve things but I'm not sure it will allow you to clearly follow the sequence.

如果您有真正的(传统)串行端口,并且操作系统负载不高,也许您可​​以以某种方式做到这一点.

If you had real (legacy) serial ports, and a not very loaded OS maybe you could do it somehow.

但如果您想要的是便宜的串行端口嗅探器,您可以尝试类似此解决方案.如果您在端口上进行转发,您将始终知道来自何处的信息.当然,您需要有权访问通信的任何一方.

But if what you want is a serial port sniffer on the cheap you can try something like this solution. If you do forwarding on your ports you'll know what is coming from where at all times. Of course, you need to have access to either side of the communication.

如果您没有那么奢侈,我想几乎可以使用任何类型的微控制器轻松获得您想要的东西.

If you don't have that luxury, I guess it would be quite easy to get what you want with almost any kind of microcontroller.

另一个想法可能是使用双串行端口到 USB 转换器.由于两个端口都由同一个芯片提供服务,因此我认为您可能可以按照其中之一的顺序进行操作.我可以访问 这个 如果您发布完整的代码片段,我可以在下周对其进行测试,如果您想知道的话.

Another idea could be to use a dual serial port to USB converter. Since both ports are served by the same chip, somehow I think it's likely that you can follow the sequence with one of those. I have access to this one if you post a full working snippet of your code I can test it next week, if you're curious to know.

这篇关于如何在C或Python中实时读取多个串口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 01:24
查看更多