4

我使用 .Net Framework 2.0 Serialport 类在 C# 2.0 中编写了一个简单的应用程序,以通过 COM1 与控制器卡进行通信。

最近发生了一个问题,Read 方法返回的字节不正确。它返回了正确数量的字节,只有值不正确。不过,用 Delphi 编写的类似应用程序仍然返回正确的值。

我使用Portmon记录两个应用程序的串行端口上的活动,比较了两个日志,并在其中一些(显然)较小的不同设置,我试图尽可能地模仿 Delphi 应用程序,但无济于事。

那么,什么会影响 Read 方法返回的字节值呢?

两个应用程序之间的大多数设置是相同的。

以下是 Portmon 日志中不同的行的列表:

德尔福应用程序:

IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:dc ERR:0 BRK:0 EVT:0 XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:0 XonLimit:256 XoffLimit:256 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI:-1 RM:100 RC:1000 WM :100 WC:1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 成功掩码:RXCHAR RXFLAG TXEMPTY CTS DSR RLSD BRK ERR RING RX80FULL

C# 应用程序:

IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13 IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI:-1 RM:-1 RC:1000 WM:0 WC:1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS 掩码:RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING

更新:

正确返回的字节为:91、1、1、3、48、48、50、69、66、51、70、55、52、93(14 个字节)。最后一个值是一个简单的校验和。

返回的错误值为:91、241、254、252、242、146、42、201、51、70、55、52、93(13 个字节)。

如您所见,返回的第一个和最后五个字节是对应的。

ErrorReceived 事件表明发生了帧错误,这可以解释不正确的值。但问题是为什么 SerialPort 会遇到框架错误,而 Delphi 应用程序显然没有?

4

4 回答 4

2

好吧,似乎问题已经解决了(至少目前是这样)。

显然,框架错误导致返回不正确的值。我编写了一个 VB6 应用程序,使用 MSComm 控件,效果很好,并比较了 Portmon 生成的日志文件。

我发现了以下差异

VB6 应用程序:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:1 Replace:0 XonLimit:256 XoffLimit:256

C# 应用程序:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024

玩弄这些设置,我发现如果我设置 _serialPort.DtrEnable = true C# App 会生成以下日志条目:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:1 Replace:0 XonLimit:1024 XoffLimit:1024

这似乎可以防止框架错误,并且应用程序似乎工作正常。

于 2008-10-08T15:44:56.407 回答
0

您是否检查过数据位数、停止位和奇偶校验的设置?

奇偶校验位是一种错误检测机制。例如:如果您使用 7 个数据位和 1 个奇偶校验位发送,则第 8 位将用于检测位反转错误。如果接收器期望 8 个数据位且没有奇偶校验位,则结果将是乱码。

于 2008-09-22T22:16:33.213 回答
0

不幸的是,您没有确切提到您得到的差异类型。是偶尔出现的不同字符还是所有传入的数据都是乱码?请注意,由于SerialPort.Encoding属性的设置,系统可能会更改通过 SerialPort.Read 函数读取的字符。此设置会影响传入文本的解释,因为它是 ASCII、Unicode、UTF8 或 Windows 用于“原始字节”到“可读文本”转换的任何其他编码方案的文本。

于 2008-09-23T08:16:31.977 回答
0

如果您正在读入一个字节数组(例如:SerialPort.Read),您应该准确地获得您在 PortMon 上看到的字节。

如果您要转换为字符(SerialPort.ReadLine 或 SerialPort.ReadChar),则数据将使用当前编码(SerialPort.Encoding 属性)进行编码,这解释了您所看到的差异。

如果您想查看与线路上的字节具有相同二进制值的字符,则可以使用 Latin-1 编码,如本文所述。

例子:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")
于 2008-09-23T11:57:55.750 回答