【问题标题】:Perl Device::SerialPortPerl 设备::串行端口
【发布时间】:2016-10-23 04:39:17
【问题描述】:

在板子启动消息期间寻找正确的方法来检测一个关键字。 检测到关键字后,一秒后发送回车键。 内核是Linux。

# Serial port inisialisation is finished here.

# Read boot message
($count, $result) = $ob->read(300); # at least 300 chars coming till keyword appear

if ($result =~ m/Booting_up/) {
    print "send Enter ...\n";
    sleep 1;
    $ob->write("\r\n");
}

感谢提示

【问题讨论】:

  • 也许这对所有人来说都很清楚——问题是什么? $ob->read 是什么?
  • $ob->read 打印正确的启动消息,但它大部分时间都错过了该关键字。在腻子控制台中,用户必须在看到该关键字后按 Enter 键才能进入设备配置菜单,否则会继续正常启动(类似于 PC 重启然后用户按 F2 进入 BIOS 菜单)。 . perl 太慢所以反应?
  • 感谢您的解释。但是......它是什么类/模块? read 方法返回什么?你正在读入两个变量——得到什么? “错过了那个关键字”是什么意思?如果它收到带有关键字的消息,它怎么会错过它?
  • read 可以在打印时一次提供一行吗?然后您可以执行while (read(...)) 并在收到每一行时检查消息。例如。你能告诉我们$ob来自哪个类/模块吗?或者您能澄清一下read 的作用/方式吗?
  • 嗨,这是我的第一个串口脚本,所以无法进一步评论。现在我可以通过从头开始发送“\n”来停止启动消息(不检测 Booting_up 关键字)。效果还是一样的,停止引导信息。但是现在在发送 $ob->write("\n\n") 后看到奇怪的行为我不能发送超过 16 个字符和随后的 $ob->write $ob->write("\n\n"); sleep 3; $ob->write("cmd"); // cmd length only 16 chars

标签: linux perl serial-port tty


【解决方案1】:

看来您正在使用Win32::SerialPort 模块,或者可能是Device::SerialPort

提供与 Win32::SerialPort 模块提供的基本相同的基于对象的用户界面。

它的方法read获取读取的字节数并返回读取的数字并将它们写入给定的字符串。

您可能是“missing”这个短语,因为它超过了 300 分,并且您的代码不再阅读。尝试循环,一次获取几个字节并将它们相加,从而在小读取中构建字符串。

my bytes_in = 10;    # length of pattern, but it does NOT ensure anything
my ($read, $result);

while (1) 
{
    my ($count, $read) = $ob->read( $bytes_in ); 

    $result = $result . $read;
    if ($result =~ m/Booting_up/) {  # is it "Booting_up" or "Booting up" ?
        print "send Enter ...\n";
        sleep 1;                     # is this needed?
        $ob->write("\r\n");
        # last;                      # in case this is all you need to do
    }

    last if $count != $bytes_in;     # done reading 
}

我没有将$ob->read 语句放在循环条件中,因为文档并不清楚该方法的工作原理。您也可以简单地使用

while ( my ($count, $read) = $ob->read( $bytes_in ) ) {
    $result = $result . $read;
    if ($result =~ m/Booting_up/s) { 
        # ...
    }
    last if $count != $bytes_in;
}

我们一次读取少量字节以防止 轮询阻塞 读取出现问题,BenPen 在 cmets 中提出。见Configuration and capability methods

您可以先一次性读取该模式之前的前 300 个字节,然后一次开始读取几个(或一个)字节,这也可以最快地识别短语。

这可以进一步调整,但让我们先看看它的作用(我无法测试)。

文档还提供了一些其他可能有用的方法,特别是readlinestreamline。由于这一切都相当低级,还有其他方法,但如果您完成所有其他工作,也许这足以完成它。

【讨论】:

  • 这里的第一段代码可能没有达到我们的预期。退出条件似乎不正确。我不确切知道 read(300) 的行为方式,但它要么在文件关闭时返回更少的字节,要么在出现暂停并且自上次 read() 以来没有 300 个字节要读取时......无论哪种方式,循环退出听起来不对,因为串口永远不会自行关闭...
  • 来自文档:因为所有绑定的方法都会阻塞,所以它们应该始终与超时设置一起使用,并且不适合后台操作和轮询循环。发生超时时,sysread 方法返回的字符可能少于请求的字符。方法调用仍然被认为是成功的。如果 sysread 在接收到某些字符后超时,则实际经过的时间可能是编程限制的两倍。如果没有收到任何字节,则适用正常时序。
  • @BenPen 虽然文档没有说太多,但他们确实说$count 是读取的字节数,并提供了一个几乎是我的last ... 声明的示例。所以我认为循环退出很好。尚不清楚$result是否已填满,但必须尝试。
  • @BenPen 你为什么引用捆绑方法? read 是其中之一吗?它似乎不是。至于超时,这是一个不同的问题。 OP没有提供细节。唯一清楚的是它可能没有读取足够的数据。我将等待澄清这是如何工作的(或不工作)。
  • 好吧,如果您查看 I/O 模式,就会发现轮询或阻塞。阻塞读取等待 300 个字节准备好,然后轮询立即返回所有字节。两者都有问题,对吧?如果输出暂停,一个会阻塞最后 300 个字节,另一个会过早退出循环。
【解决方案2】:

也许宁愿索引字符串?

($count, $result) = $ob->read(300); # at least 300 chars coming till keyword appear

$substring = 'Booting_up';
 if (index($result, $substring) != -1) {
   print "send Enter ..\n";
   sleep 1;
   $ob->write("\r\n");
}

【讨论】:

    猜你喜欢
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多