在多个平台上使用Mono实现串口(RS232)通信

3
我计划使用.NET(原生C++)重新编写一个Win32应用程序,最可能使用mono,以便在Win32、Linux和mac上运行。我试图解决的问题(仅开发过Win32)是串口定义的问题。当只有一个可执行文件时,如何通常识别平台之间的差异?具体来说,在Windows中将COM端口标识为COM1或类似于(\.\COM),但在Linux上它们被指定为/dev/ttyS0这样的东西。
是否在运行时为此信息检查平台?我认为唯一的区别在于打开和关闭端口。读取和写入是相同的。也许这是一个更通用的问题,因为它适用于mono/.NET中的任何特定于平台的内容。
你如何处理这个问题?在某些字符串资源或配置文件中,还是硬编码并根据运行时平台进行切换?
有关此代码示例吗?请注意,我是C++开发人员,并不熟悉.NET中所有可用的类。是否有一种方法可以从CLR获取串口命名方案,或者是否有一种方法可以从CLR获取操作系统/平台?
CLR能否以更独立的方式呈现串口将是很好的。也许这是不可能的。
谢谢, Tim
编辑
鉴于目前只有一个回复,我想先尝试SerialPort.GetPortNames()枚举,看看它是否起作用。(在两个平台上)
对于USB dongle和更高的端口号,在win32中,它并不像基本的COM端口枚举那样简单。
我将在这里报告研究结果。
3个回答

4
在.Net中,您需要使用System.IO.Ports。像“COM1”和“/dev/ttyS0”这样的名称是随机的操作系统名称。为什么要硬编码它们?用户应该只从可用端口列表中选择一个。
显然,您需要在运行时确定此列表。事实上,对于USB串口适配器,您可能需要考虑一种可能性,即用户在启动程序后才发现忘记连接USB串口适配器。这意味着每次显示配置对话框时都应重新读取此列表。顺便说一下,USB适配器很可能不是COM1。
(我不能保证SerialPort的Mono实现质量。快速谷歌搜索让我有点担心,但请自行测试)

是的,关于Linux和Mono的这个“令人担忧”的问题就是我提问的原因。我应该尝试枚举并查看它是否有效。 - Tim

3
我看了一下,似乎枚举串行端口的Mono代码只能在Linux上运行。 (来自mcs/class/System/System.IO.Ports/SerialPort.cs)
            public static string [] GetPortNames ()
            {
                    int p = (int) Environment.OSVersion.Platform;
                    List<string> serial_ports = new List<string>();

                    // Are we on Unix?
                    if (p == 4 || p == 128 || p == 6) {
                            string[] ttys = Directory.GetFiles("/dev/", "tty*");
                            foreach (string dev in ttys) {
                                    if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
                                            serial_ports.Add(dev);
                            }
                    } else {

在OSX上,我认为您可能可以匹配/dev/tty.*(FreeBSD需要/dev/ttyU[0-9]+)。
我不能说我喜欢它选择运行的操作系统的方式。

1

刚刚发现了这个帖子,想要分享我的发现:我也担心在Mac上会出现这种情况。在Windows和Linux(无论是在VS还是Mono中),SerialPort.GetPortNames()都会返回一个列表,并遵循以下规则:

1)Windows返回一个字符串列表,例如Com1、Com4,省略任何不存在的端口(USB串行适配器似乎会根据插入的插头取一个COM号码,始终如一)。从我的串口扫描器中可以看到:

正在扫描COM1 正在扫描COM4 扫描完成

2)Linux返回所有可能由Linux发行版编译器启用的tty串行端口。这似乎是大约8个端口,如果您尝试打开它们,将会抛出异常(从我的串口扫描器中可以看到:

正在扫描 /dev/ttyS0 正在扫描 /dev/ttyS1 端口失败System.IO.IOException: I/O 错误 at System.IO.Ports.SerialPortStream..ctor (System.String portName, Int32 baudRate, Int32 dataBits, Parity parity, StopBits stopBits, Boolean dtrEnable, Boolean rtsEnable, Handshake handshake, Int32 readTimeout, Int32 writeTimeout, Int32 readBufferSize, Int32 writeBufferSize) [0x00000] at (wrapper remoting-invoke-with-check) System.IO.Ports.SerialPortStream:.ctor (string,int,int,System.IO.Ports.Parity,System.IO.Ports.StopBits,bool,bool,System.IO.Ports.Handshake,int,int,int,int) at System.IO.Ports.SerialPort.Open () [0x00000] at (wrapper remoting-invoke-with-check) System.IO.Ports.SerialPort:Open () at HSMScanner.Program.Main (System.String[] args) [0x00000] 正在扫描 /dev/ttyS2 端口失败System.IO.IOException: I/O 错误 at System.IO.Ports.SerialPortStream..ctor (System.String portName, Int32 baudRate, Int32 dataBits, Parity parity, StopBits stopBits, Boolean dtrEnable, Boolean rtsEnable, Handshake handshake, Int32 readTimeout, Int32 writeTimeout, Int32 readBufferSize, Int32 writeBufferSize) [0x00000] at (wrapper remoting-invoke-with-check) System.IO.Ports.SerialPortStream:.ctor (string,int,int,System.IO.Ports.Parity,System.IO.Ports.StopBits,bool,bool,System.IO.Ports.Handshake,int,int,int,int) at System.IO.Ports.SerialPort.Open () [0x00000] at (wrapper remoting-invoke-with-check) System.IO.Ports.SerialPort:Open () at HSMScanner.Program.Main (System.String[] args) [0x00000] 正在扫描 /dev/ttyS3 端口失败System.IO.IOException: I/O 错误 at System.IO.Ports.SerialPortStream..ctor (System.String portName, Int32 baudRate, Int32 dataBits, Parity parity, StopBits stopBits, Boolean dtrEnable, Boolean rtsEnable, Handshake handshake, Int32 readTimeout, Int32 writeTimeout, Int32 readBufferSize, Int32 writeBufferSize) [0x00000] at (wrapper remoting-invoke-with-check) System.IO.Ports.SerialPortStream:.ctor (string,int,int,System.IO.Ports.Parity,System.IO.Ports.StopBits,bool,bool,System.IO.Ports.Handshake,int,int,int,int) at System.IO.Ports.SerialPort.Open () [0x00000] at (wrapper remoting-invoke-with-check) System.IO.Ports.SerialPort:Open () at HSMScanner.Program.Main (System.String[] args) [0x00000]

3) Macs...

哦,亲爱的。当USB串口插入并且驱动程序和一切都正常时,Mac电脑在GetPortNames()上不返回任何东西。在/dev/tty中查看,只有在设备插入并且具有类似于/dev/tty.usbserial-A7006Ro7的名称时,额外的设备才会出现,不幸的是,将此名称用作程序的参数,然后跟随serial.open似乎没有任何效果。

进一步研究。


感谢这个补充。由于没有得到想要使用Mac或Linux的用户的反馈,那个项目已经停滞了。我曾经以为会有很多人使用,但是到目前为止,这个项目只是出于我的好奇心。 - Tim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接