【问题标题】:Automating serial port communication on Linux在 Linux 上自动进行串行端口通信
【发布时间】:2011-04-21 22:27:33
【问题描述】:

我有一个 linux 服务器 (Red Hat 4),其中一个串口连接到嵌入式 linux 设备,另一个串口连接到该设备的电源控制器。我目前控制它们的方法是打开两个 minicom 会话,每个会话都在自己的窗口中。我想通过脚本自动化这种通信。起初,我开始思考如何使用 minicom 实现自动化,然后意识到当脚本应该能够直接与端口对话时,我不应该尝试使用控制台应用程序实现自动化。

我知道一些 Perl 和一些 python。我以前没有调制解调器通信(使用 AT 命令)的经验。 Perl 有 Device::Modem,虽然它只是测试版,而且 Perl 似乎是一个不错的选择,因为我更喜欢它的文本提取和争论能力。但是,如果我需要学习如何控制调制解调器和编写/调试脚本,这会增加我的任务时间。

是否可以/常见使用脚本以交互方式控制 minicom 等控制台应用程序?如果没有,我有什么好的资源来学习如何使用调制解调器 AT 命令?还是有其他资源可以为我简化事情?

【问题讨论】:

    标签: linux automated-tests serial-port modem


    【解决方案1】:

    Kermit 是一个类似于 minicom 的串行通信应用程序,它有自己的脚本语言,我用它在嵌入式设备上进行一些自动上传。但是,它非常有限和/或有问题,所以我最终改用 python 和 pyserial。
    每当您处理文本模式时,例如 AT 命令集或通过串行线路与 shell 对话,它都非常强大。

    如果我需要使用一些标准协议进行二进制传输,我通常在非交互模式下使用命令行工具,并从我的 python 脚本中生成它们。

    这是我构建的工具的一部分:等待输入,通过 xmodem 发送数据,向 u-boot 发送命令并使用 kermit 协议开始传输。我用它来自动刷新和测试嵌入式设备。

    class Parser :
        def __init__(self, sport_name):
            self.currentMsg = ''
            if sport_name :
                self.ser = serial.Serial(sport_name, 115200)
        def WaitFor(self, s, timeOut=None):
            self.ser.timeout = timeOut
            self.currentMsg = ''
            while self.currentMsg.endswith(s) != True :
                # should add a try catch here
                c=self.ser.read()
                if c != '' :
                    self.currentMsg += c
                    sys.stdout.write(c)
                else :
                    print 'timeout waiting for ' + s
                    return False
            return True
    
        def XmodemSend(self,fname):
            if not self.WaitFor('C', 1) :
                print 'RomBOOT did not launch xmodem transfer'
                return
            self.ser.flushInput()
            self.ser.close()
            call(["xmodem","-d",self.ser.port,"-T",fname])
            self.ser.open() 
    
    def UbootLoad(self, fname):
        self.ser.write('loadb 0x20000000\n')
        if not self.WaitFor('bps...',1) :
            print 'loadb command failed'
            sys.exit()
        self.ser.flushInput()
        self.ser.close()
        retcode=call(['kermit','-y','kermit_init','-s',fname])
        if retcode != 0 :
            print 'error sending' + fname
            sys.exit()
        self.ser.open()
        self.UbootCmd('echo\n')
    

    【讨论】:

    • 谢谢!我发现 minicom 有一个叫做 runscript 的实用程序,它很简陋但足够了。但是,非常感谢您发布该内容。将来我很可能会发现这很有用。
    【解决方案2】:

    我发现了 runscript ("$ man runscript"),这是一个实用程序,它为 minicom 添加了类似期望的脚本功能。预期行为对我很有用,因为该设备使用专有的交互式启动序列。它很简陋,但足够了。可以在使用“-S scriptname”标志启动 minicom 时调用脚本,并且可以将脚本中的特定文本发送到日志文件,这在从脚本运行 minicom 时很有用。我还没有找到将控制台内容发送到日志的方法,因此让外部脚本知道 minicom 内部发生的事情涉及写入日志并让脚本监视日志。我计划仅使用 runscript 来重新启动并进入 shell,然后在更高级别的语言脚本(如 Python 或 Perl)中通过 ssh 连接到设备以进行真正的交互。如果还没有 minicom,我会采用 shodanex 的方法。

    Runscript 不能有嵌套的期望。我通过使用 goto 和标签解决了这个问题,这可以说比嵌套预期的更具可读性:

    expect {
       "Condition 1"  goto lable1
    }
    
    lable1:
        send "something"
        expect {
           "Condition 2"  goto label2
        }
    lable2:
        # etcetera
    

    【讨论】:

    • 更正:当使用“-C logfilename”调用 minicom 时,控制台输出将被捕获到该文件。
    • 您的脚本中有拼写错误,“lable”与“label”。
    • runscript 看起来不错,但我看不到发送文件的方法,所以它适合我。
    【解决方案3】:

    我正在使用这样的电源控制器,我使用 RS232 来控制。

    我使用 bash 编写脚本,只需发出:

    echo "your-command" > /dev/ttyUSB0
    

    我正在使用的特定设备也使用 300 波特率,所以我发出:

    stty -F /dev/ttyUSB0 300
    

    提前。

    【讨论】:

      【解决方案4】:

      如果只是控制设备而不是其他(如处理消息、与其他操作系统服务交互等),您可以使用chat 程序。它正是为此而写的。 您可以在任何 Linux 发行版的 ppp 包中找到它。

      【讨论】:

      • 感谢您告诉我有关聊天程序的信息。它可以满足我的部分需求,但实际上我必须能够在进入 shell 之前下载并启动一个新的 linux 映像到这个设备。设备使用busybox。
      【解决方案5】:

      Python 现在有 PySerial 库:http://pyserial.sourceforge.net/

      Ruby 有 SerialPort gem:http://rubygems.org/gems/serialport

      Perl 可能有类似的库,但我找不到。

      我从非常有用的 Arduino Playground 中发现了这两个: http://playground.arduino.cc//Main/Interfacing

      CJ

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-05
        • 2014-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-13
        • 1970-01-01
        • 2012-11-22
        相关资源
        最近更新 更多