【问题标题】:C#/.NET wrapper for serial port WIN32 Comm API串口 WIN32 Comm API 的 C#/.NET 包装器
【发布时间】:2017-01-19 03:26:51
【问题描述】:

我正在寻找一种方法来尽可能多地控制我的 c# 应用程序中的串行端口。问题是我需要与一个没有文档的设备进行通信,除了一个为控制它而编写的旧 c++ 程序。我尝试使用 SerialPort 类与设备通信,但它的行为很奇怪(我必须重复一些命令,其他一些命令根本不起作用)。 我想复制该非托管程序的行为,但是使用串行端口类似乎是不可能的,因为它不提供对低级函数和结构(例如 DCB)的访问。

是否有可用于 .net 的串行通信的低级包装器?也许我可以在运行时使用反射来操作串行端口不可访问的成员?

【问题讨论】:

  • 你检查过SerialPort类的所有属性了吗?只有极少数的东西没有被映射。

标签: c# serial-port


【解决方案1】:

对于那些建议查看 .NET SerialPort 类的人;关于串行相关问题的常见 Stack Overflow 答案提供者 Ben Voigt 提供了一些极好的见解,说明为什么围绕 WinAPI 的包装器最终会比使用提供的 SerialPort 框架更好:

Ben Voigt on .NET SerialPort

必读。

他还提到了一个 WinAPI 包装器,他可能会在以后的博文中透露。如果发生这种情况,它将回答最初的问题。

此外,似乎至少有一种商业解决方案可以提供所需的功能here

另一个编辑:

更多的在线搜索已经产生了this blog post,显然是从 .NET 中没有 SerialPort 类的时候开始的......提供了源代码,展示了如何为此目的包装 Win32 API。

编辑

有用户指出,上述MSDN博文链接已失效。

链接文章的标题是:

Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications”,由 John Hind 撰写并于 2002 年 10 月出版,正如我从另一篇 MSDN 文章中提到的那样:

不幸的是,微软似乎只提供他们杂志到 2003 年的版本:

FWIW,我在别处找到了half working online version...

【讨论】:

  • 我不介意投反对票,但也请提供反馈。
  • MSDN 博客文章的链接已损坏。如果可能,也包括文章标题,以防链接再次断开。
  • 我去找!
【解决方案2】:

不幸的是,SerialPort 类是一个不完整的包装器。我发现访问底层 DCB 的唯一方法是通过反射。

唯一的其他选择是重新编写 SerialPort 并使其完整。我还没有看到任何这样的免费实现。

以下是我使用反射来访问 RTS_CONTROL_TOGGLE 的示例: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/45a89532-b01c-4ef8-aa46-532882cec004

【讨论】:

    【解决方案3】:

    SerialPort 类是 Win32 串行端口 API 的一个非常薄的包装器,很难看出另一个包装器如何改善您的生活。从 .NET 1.x 开始就有包装器可用,它不支持串行端口。这是来自MSDN magazine 的一封邮件。

    但您也很可能遇到同样的问题。写入命令可能丢失的一种方法是设备在关闭 RTS 信号时丢弃接收到的字节(或丢失它们)。您可以通过将 Handshake 属性设置为 RequestToSend 来解决此问题。

    读取命令可能出错的一种方法是错误地调用 Read()。它将返回任意数量的字节,与接收缓冲区中可用的字节数一样多。注意返回值,它告诉你实际读取了多少字节。唯一的保证是它至少为 1 且永远不会超过 count

    SysInternals 的PortMon utility 可以帮助您排除通信故障,它可以让您对设备驱动程序看到的内容有一个原始视图。与 Hyperterminal 或其他已知良好的程序进行比较。

    【讨论】:

    • PortMon 参考非常有用,谢谢
    • 一点也不。它引入了SerialStream 层,该层又使用重叠(失败异步)winapi 方法。 SerialPort 有很多麻烦,我现在也在寻找一个真正的 thin 包装器:DataReceived 事件是垃圾,端口关闭异常,ObjectDisposedException(呵呵)当 USB-转串口适配器断开等。
    • 嗯,如果您不喜欢 ODE,请不要在端口打开时猛拉连接器。这样做完全没有意义。当您使用 USB 模拟器时,使用“安全删除硬件”托盘图标不是可选的,串行端口不是播放和播放设备。
    • @HansPassant,您不能指望您的最终用户或硬件技术人员遵循您的所有指示。大多数时候,他们甚至不阅读说明。当ObjectDisposedException 发生时,您的应用程序将变得不稳定,并且无法避免这种情况,即使您试图告诉他们这是微软的错,管理层也会责备您编写糟糕的代码!
    • 我为程序员而不是技术人员写答案。技术人员永远不会有任何麻烦找出拔掉电缆 => 程序崩溃 => 不是一个好策略。你更喜欢拔掉电缆 => 停止工作 => 调用程序员的方法,试试吧。
    【解决方案4】:

    通过 PInvoke 使用串行端口可以正常工作。我们在 Silverlight 应用程序中执行此操作,但它在普通 .NET 应用程序中的工作方式应该相同。 Serial Communication with Silverlight 5 (COM port) 的答案为 a 提供了一个基本的包装器,可以很容易地适应您的需求。它使用普通的 WinAPI 方法,因此您可以完全访问所有串行端口功能,就像在 C++ 应用程序中一样。

    附:如果您还没有,请使用PortMon 来监控在线上发生的事情。

    【讨论】:

    • 感谢您对其他答案的了解。那里发布的代码似乎很有用。在 32 位 Win7 上,Portion 确实是一个不错的工具。我的经验是它不适用于 x64 (stackoverflow.com/questions/1356470/…)。即使以管理员身份运行并设置 WinXP SP2/3 兼容性也无济于事。很遗憾,因为它是一个不错的工具。
    • 我最终使用了您引用的解决方案,它们非常适合我的目的。谢谢。
    【解决方案5】:

    您可以将旧的 C++ 代码复制到托管 C++ 类中,然后您可以像使用 C# 代码中的任何普通 .NET 类一样使用它。这可能是实现目标的最快方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 2023-03-04
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多