在Linux上自动执行串行端口通信

时间:2010-10-06 16:11:34

标签: linux automated-tests serial-port modem

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

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

使用脚本以交互方式控制像minicom这样的控制台应用程序是否可能/通用?如果没有,有什么好资源让我学习如何使用调制解调器AT命令?或者是否有其他资源可以简化我的事情?

5 个答案:

答案 0 :(得分:5)

我发现了一个运行脚本(“$ 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

答案 1 :(得分:4)

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')

答案 2 :(得分:2)

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

答案 3 :(得分:2)

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

我只需发出以下命令使用bash编写脚本:

echo "your-command" > /dev/ttyUSB0

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

stty -F /dev/ttyUSB0 300

之前。

答案 4 :(得分:1)

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

Ruby拥有Seri​​alPort gem:http://rubygems.org/gems/serialport

Perl可能有类似的库,但我无法找到它。

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

CJ