8

我正在寻找一种使用外部 TTL 脉冲触发我的数据采集软件的简单方法。我需要使用 5 Hz 参考时钟同步地从多个源中采样数据。采集不需要实时优先级,但我想确保我的软件尽快触发,并且每个外部时钟周期准确触发一次。我宁愿通过某种方式从外部触发器获取中断来做到这一点,而无需使用快速轮询循环。据我所知,在 Linux 等现代操作系统中,您不能只使用并行端口引脚来中断。有任何想法吗?

我也在考虑在我的网络上生成广播数据包,以通知网络上的其他机器发生了触发事件。然而,由于网络延迟,在触发之间的 200 毫秒期间可能没有足够的时间来进行采集。

4

4 回答 4

10

您是否考虑过使用串行设备而不是使用并行端口?由于您有 TTL 信号,您可能需要一个电平转换器将 TTL 转换为 RS232 +/- 12V 电平。使用串行设备后,您可以使用标准串行ioctl()调用来检测控制信号状态的变化。

具体来说,您可以使用TIOCMIWAIT连接的串行设备上的 ioctl 来等待 DCD 线路的变化,您将连接到您的时钟源。

您的用户空间应用程序将在TIOCMIWAITioctl 系统调用中等待,直到时钟线上的状态发生变化,此时您的应用程序将变为可运行并从 ioctl 返回。您可能需要注意确保处理在串行控制信号的上升沿和下降沿都发生状态变化中断的情况。在某些 UART 硬件(例如 TL16C554A UART)上,您可能只会收到单向信号转换的中断。例如,对于 TL16C554A,它TIOCMIWAIT只会在任何 Ring Indicate 信号变化的上升沿下降。

以这种方式使用串行 ioctl 还具有优势,即您可以使用支持TIOCMIWAIT(例如 PL2303)的 USB 串行加密狗,并且仍然保持用户级软件兼容性,尽管以 USB 导致的延迟增加为代价。

如果您需要比通过用户空间实现的延迟更低的延迟,您最好编写一个可以处理时序和采样的内核驱动程序模块,但除非绝对需要,否则我不建议使用此路线。开发用户空间代码更容易。

下面是一些使用TIOCMIWAITioctl 的不完整示例 C 代码片段。

int serial_fd = open(cmdline.device_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
static const unsigned int ri_flag = TIOCM_RNG;

/* Set up serial port here using tcsetattr.  Set CRTSCTS | CLOCAL to ensure status interrupts
 * are generated.
 */

while (1) {
        /* Wait for positive RI transition.  TIOCMIWAIT takes a mask
         * as argument, only returning when the appropriate signal has changed.
         */
        if (ioctl(serial_fd, TIOCMIWAIT, ri_flag)) {
            fprintf(stderr, "ioctl() failed waiting for RI edge [%s]\n", strerror(errno));
            break;
        }

        /* Do sensor sampling here.  You could use TIOCMGET to first verify that
         * the clock line is in the expected state, eg high, before continuing.
         */
}
于 2013-07-02T02:21:47.910 回答
3

对于如此低的数据速率,轮询是一种很好的方法。1 毫秒轮询。那应该没问题。尝试使用硬件中断会造成很大的痛苦。

如果您想以艰难的方式执行此操作,请在 Google 上搜索“中断 Linux GPIO”。:)

https://developer.ridgerun.com/wiki/index.php/How_to_use_GPIO_signals

于 2013-07-02T00:11:06.293 回答
3

考虑将外部脉冲源连接到真实(!不是 USB 到 RS232 转换器)串行端口的“CD”ping。然后,您可以使用“PPS api”获取引脚“变高”的尽可能准确的时间戳。

您可能需要一个 TTL 信号转换器;并非所有串行端口都能在 TTL 信号电平下正常工作。

PPS api 通常用于计时。例如,将 GPS 模块的 PPS 引脚连接到您的 pc 并让 NTP 与之同步。这为您提供微秒级精度。

这个 PPS api 应该比任何其他用户空间解决方案(例如 TIOCMIWAIT ioctl)更准确,因为它完全在内核中处理,当中断(由 CD 信号更改触发)进入时立即。使用 ioctl 解决方案,您至少有一个上下文切换。我在树莓派上做了一些测试,用户空间解决方案提供了至少 6us 的抖动。

PPS api 会为您提供检测到脉冲时的时间戳。

为什么不使用 USB 到 RS232 转换器:我在某处(关于计时)读到 USB 设备每 +/- 1 毫秒轮询一次。这个轮询频率还取决于系统对其他 USB 设备的繁忙程度,我认为 USB 设备的内部时钟也可能会影响事情。我从来没有测量过这个。

相关网址:

关于网络功能:使用 UDP 广播,不要使用 TCP。

于 2013-09-05T10:01:06.027 回答
2

我最终使用串行端口 CTS 线使用TIOCMIWAITioctl per Austin Phillips 答案作为触发器。由于 RS232 需要 +/-12V 电平,我能够从其他串行控制线获得此电平转换器所需的电源。

电平转换器示意图

可以找到实现此解决方案的 Python 代码:Python monitor serial port (RS-232) handshake signals

于 2013-07-05T20:13:13.297 回答