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

C# 在Mono Linux上使用SerialPort时出现高波特率错误,c#,python,linux,mono,serial-port,C#,Python,Linux,Mono,Serial Port,我必须通过FTDI RS485连接器与设备进行单声道通信,该连接器具有1000000波特率的通用通信软件接口。操作系统Linux Ubuntu。。。特别是Mint13,mono 2.10.2 首先,我在Linux上运行简单的python测试程序: >> import serial >> ser = serial.Serial("/dev/ttyUSB0",1000000, timeout=0.5) >> ser.write(":DCS3FF8;")

我必须通过FTDI RS485连接器与设备进行单声道通信,该连接器具有1000000波特率的通用通信软件接口。操作系统Linux Ubuntu。。。特别是Mint13,mono 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)
使用以下命令编译并运行它:

     dmcs serial_try.cs && mono serial_try.exe
并获取TimeoutException,serialPort.BytesToRead为0。同时,我看到连接器闪烁着两个指示灯,有东西在传输

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


那么,mono上的SerialPort有什么特点呢?我是否错过了一些设置或配置

在mono上读取FTDI设备的问题被发现是由以下原因引起的

错误的想法是:如果将波特率设置为921600以上,则实际波特率设置为9600

有趣的是,如果你浪费时间想弄明白为什么你不能在mono上与SerialPort通信,这与。其中说明无法设置波特率921600。因此,看起来这个bug被修复到了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的建议修复mono bug


更新如果波特率是非ASCII的,因此不能使用stty,则可以使用python作为解决方案。见下面的评论。多亏了@Dorian Scholz.

在mono上读取FTDI设备的问题被发现是由以下原因引起的

错误的想法是:如果将波特率设置为921600以上,则实际波特率设置为9600

有趣的是,如果你浪费时间想弄明白为什么你不能在mono上与SerialPort通信,这与。其中说明无法设置波特率921600。因此,看起来这个bug被修复到了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的建议修复mono bug


更新如果波特率是非ASCII的,因此不能使用stty,则可以使用python作为解决方案。见下面的评论。多亏了@Dorian Scholz。

事件没有实现,我以前在使用MS.NET编写/读取扁平字符串时也遇到过问题,因为它不允许自定义编码-您是否尝试编写字节[]?是的。我查过了。这一切都很好。那么,恐怕你需要亲自查看并尝试修复文本编码层。事件没有实现,我以前在MS.NET中也遇到过写/读平面字符串的问题,因为它不允许自定义编码-你尝试过写字节[]吗?是的。我查过了。这一切都很好。那么,恐怕你需要亲自查看并尝试修复文本编码层。感谢这一点,它帮助我让Reepier Host 3D打印软件在Linux上与Solidoodle 2打印机配合使用。我不得不稍微修改一下您的解决方案,因为打印机运行的是250000波特,这是非ansi的,因此stty不支持。但是使用python作为可执行文件,使用最小脚本作为参数,它工作得很好:string arg=string.Format-c\import serial;serial.serial'{0}',{1}\,端口,波特率;感谢这一点,它帮助我让Repetier Host 3D打印软件在Linux上与Solidoodle 2打印机配合使用。我不得不稍微修改一下您的解决方案,因为打印机运行的是250000波特,这是非ansi的,因此stty不支持。但是使用python作为可执行文件,使用最小脚本作为参数,它工作得很好:string arg=string.Format-c\import serial;serial.serial'{0}',{1}\,端口,波特率;