在Mono Linux上使用SerialPort时出现高波特率的错误

时间:2012-11-03 06:08:15

标签: c# python linux mono serial-port

我必须通过FTDI RS485连接器(具有通常的comport软件接口)以1000000波特率在Mono中与设备进行通信。 OS - Linux(Ubuntu ...... Mint13特别),单声道2.10.2。

首先我在Linux上运行简单的python测试程序:

 >> import serial
 >> ser = serial.Serial("/dev/ttyUSB0",1000000, timeout=0.5)
 >> ser.write(":DCS3FF8;")   # Some message to the device with crc
 >> ser.readall()
 ':CDS P0 M0 E0 L1 S07B3B;'  #This is the correct response from the device

 >> print ser
 Serial<id=0x2ce71d0, open=True>(port='/dev/ttyUSB0', baudrate=1000000, bytesize=8, parity='N', stopbits=1, timeout=0.5, xonxoff=False, rtscts=False, dsrdtr=False)

设备正确响应。一切正常。这表明Linux上的一切运行正常。

然后我退出python并尝试使用Mono代码:

     var serialPort = new SerialPort();
     serialPort.PortName = "/dev/ttyUSB0";
     serialPort.BaudRate = 1000000;

     serialPort.Open();
     serialPort.Write(":DCS3FF8;");
     Thread.Sleep(150);
     Console.WriteLine("BytesToRead: '{0}'", serialPort.BytesToRead);
     Console.WriteLine("Existing   : '{0}'", serialPort.ReadExisting());

使用命令编译并运行它:

     dmcs serial_try.cs && mono serial_try.exe

得到TimeoutException,serialPort.BytesToRead为0.同时我看到连接器闪烁着两个灯(某些东西正在转移)。

当我在Windows上运行相同的代码时,与设备成功通信并收到与python相同的消息。

那么单声道SerialPort的问题是什么?我是否会错过一些设置或配置?

1 个答案:

答案 0 :(得分:4)

发现在单声道上读取FTDI设备的问题是由bug with baud rate引起的。

错误的想法:如果设置波特率大于921600,则实际波特率设置为9600.

有趣的是(如果你浪费时间试图找出无法与单声道上的SerialPort通信的原因),这与older bug有关。如果不可能设置波特率921600。因此看起来这个错误已经被修复到了921600并且没有多少。

要解决此问题,可以在端口打开后调用stty来设置实际波特率。所以添加这个功能:

    private void ForceSetBaudRate(string portName, int baudRate)
    {
        if (Type.GetType ("Mono.Runtime") == null) return; //It is not mono === not linux! 
        string arg = String.Format("-F {0} speed {1}",portName , baudRate);
        var proc = new Process
            {
                EnableRaisingEvents = false,
                StartInfo = {FileName = @"stty", Arguments = arg}
            };
        proc.Start();
        proc.WaitForExit();
    }

连续打开后立即致电:

    _serialPort.PortName = PortName;
    _serialPort.BaudRate = BaudRate;
    _serialPort.Open();
    ForceSetBaudRate(PortName, BaudRate);

黑客并不漂亮,但最终FTDI调制解调器适用于Mono + Linux和.Net + Windows。

其他解决方法可能是实现您自己的串口包装器和PInvoking它或修复单声道错误,如@skolima建议的那样。

更新如果波特率是非ASCII,那么不能使用stty,python可以用作解决方案。见下面的评论。感谢@Dorian Scholz。