【发布时间】:2012-11-05 14:44:33
【问题描述】:
我一直在开发一个在 SerialPort 上进行通信的程序,但遇到了问题。它的通信率低于 50% 或更少。如果没有,它大部分时间都会超时。
根据我对这个问题的研究,我发现默认情况下全局或系统计时器分辨率至少为 10 毫秒或更大。
Serial Communication (RTS) and Windows 7
因此,如果您在通信中使用 Thread.Sleep 暂停 X 毫秒,那么它可以做的最好的事情是 10 毫秒或更长的无操作或暂停。
就我而言,这对于我的程序与外部设备通信来说太长了。设备收到我的程序的请求后会在 10 毫秒内回复。如果我的程序还没有准备好接收回复,那么我的程序将超时。
解决此问题的唯一方法是调整或更改系统计时器分辨率。为此,我被告知使用来自 winmm.dll 的 Windows 方法 timeBeginPeriod 和 timeEndPeriod。虽然我可以为我的 Windows .NET 版本的程序导入这些方法,但我想知道在 .NET 框架中是否有这些方法的替代品。
【问题讨论】:
-
SerialPort 的 DataReceived 事件的响应与定时器分辨率无关。它使用可等待事件,当驱动程序发出“数据接收”事件时,该事件会导致线程上下文切换。期望保证 10 毫秒的响应在 Windows 上是一个失败的原因,它不是一个实时操作系统。需要驱动程序。
-
@HansPassant,不。这与 DataReceived 无关。我也试过了,它本身给我带来的悲伤比解决我的问题更多。因此,我创建了一个用于通过串行端口进行写入和读取的线程。确切地知道设备需要多长时间才能回复,我暂时停下来让我的软件切换 LINE (RTS) 进行读取。一旦读取它就会切换行(rts)进行写入。它只需要 2 或 3 毫秒。所以,我使用thread.sleep。如上所述,thread.sleep(1) 将等待 10 毫秒或更长时间。汉斯,它可能会丢失,但在 3 周的头痛之后,到目前为止我的沟通已经 100% 稳固
-
这没什么意义。为什么要睡觉?直接调用 Read() 不用any sleep,它只在收到东西时返回。
-
@HansPassant,需要驱动程序??? Visual Studio 2010 自带的还不够吗?我没有安装任何特别的东西。我正在使用 Visual Studio 2010 附带的框架工具 SerialPort。经过几次设置后,我就可以进行通信了。它可能正在使用通用驱动程序。
-
在我看来,您在从串行端口读取数据时犯了一个非常经典的错误。您忽略了 SerialPort.Read() 调用的返回值。它不是是您要求的字节数。是的,调用 Sleep() 是一种创可贴,它会延迟您的程序足够长的时间以允许驱动程序接收足够的字节。然而,这不是正确的解决方法,您应该继续调用 Read() 直到获得整个设备响应。
标签: .net serial-port delphi-prism oxygene winmm