简体   繁体   English

什么会影响Serialport.Read()返回的值

[英]What Could Affect Values Returned By Serialport.Read()

I've written a simple app in C# 2.0 using the .Net Framework 2.0 Serialport class to communicate with a controller card via COM1. 我已经使用.Net Framework 2.0 Serialport类在C#2.0中编写了一个简单的应用程序,以通过COM1与控制器卡进行通信。

A problem occurred recently were the bytes returned by the Read method are incorrect. 最近发生的问题是Read方法返回的字节不正确。 It returned the right amount of bytes, only the values were incorrect. 它返回正确的字节数,只有值不正确。 A similar app written in Delphi still returned the correct values though. 但是,用Delphi编写的类似应用程序仍返回正确的值。

I used Portmon to log the activity on the serial port of both apps, compared the two logs and there where some (apparently) minor different settings and I tried to the imitate the Delphi app as closely as possible, but to no avail. 我使用Portmon在两个应用程序的串行端口上记录了活动,比较了两个日志,并在那里找到了一些(显然)次要的不同设置,并且我尝试尽可能地模仿Delphi应用程序,但无济于事。

So, what could affect the byte values returned by Read method ? 那么,什么会影响Read方法返回的字节值呢?

Most settings between the two apps are identical. 两个应用之间的大多数设置都是相同的。

Here is a list of the lines which differed in the Portmon log : 以下是Portmon日志中不同的行的列表:

Delphi App : Delphi应用程序:

IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:dc ERR:0 BRK:0 EVT:0 XON:11 XOFF:13 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 SUCCESS Mask: RXCHAR RXFLAG TXEMPTY CTS DSR RLSD BRK ERR RING RX80FULL IOCTL_SERIAL_SET_HANDFLOW的Serial0成功摇:0替换: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 SUCCESS面膜:RXCHAR RXFLAG TXEMPTY CTS DSR RLSD BRK ERR RING RX80FULL

C# App : 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 Mask: RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING 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: WM:0 WC:1000 IOCTL_SERIAL_SET_WAIT_MASK串行0成功掩码:RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING

UPDATE: 更新:

The correct returned bytes were : 91, 1, 1, 3, 48, 48, 50, 69, 66, 51, 70, 55, 52, 93 (14 bytes). 正确的返回字节为:91、1、1、3、48、48、50、69、66、51、70、55、52、93(14个字节)。 The last value being a simple checksum. 最后一个值是简单的校验和。

The incorrect values returned were : 91, 241, 254, 252, 242, 146, 42, 201, 51, 70, 55, 52, 93 (13 bytes). 返回的错误值是:91、241、254、252、242、146、42、201、51、70、55、52、93(13个字节)。

As you can see the first and the last five bytes returned correspond. 如您所见,返回的前五个字节对应。

The ErrorReceived event indicates that a framing error occurred, which could explain the incorrect values. ErrorReceived事件表明发生了帧错误,这可能解释了错误的值。 But the question is why would SerialPort encounter a framing error when the Delphi app apparently does not ? 但是问题是,为什么Delphi应用程序显然没有,SerialPort为什么会遇到成帧错误?

Well, it seems as if the problem has been resolved (at least for the time being). 好吧,看来问题已经解决了(至少暂时没有解决)。

Apparently a framing error caused the return of incorrect values. 显然,成帧错误导致返回不正确的值。 I wrote a VB6 app, using the MSComm control, which worked fine, and compared the log files generated by Portmon. 我使用MSComm控件编写了一个VB6应用程序,该应用程序运行良好,并比较了Portmon生成的日志文件。

I picked up the following differences 我总结了以下差异

VB6 App : VB6应用程序:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:1 Replace:0 XonLimit:256 XoffLimit:256 IOCTL_SERIAL_SET_HANDFLOW串行0成功摇动:1替换:0 XonLimit:256 XoffLimit:256

C# App : C#应用程序:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024 IOCTL_SERIAL_SET_HANDFLOW串行0成功摇动:0替换:0 XonLimit:1024 XoffLimit:1024

Playing around with the settings I found that if I set _serialPort.DtrEnable = true the C# App generates the following log entry : 进行设置,我发现如果我设置_serialPort.DtrEnable = true则C#App会生成以下日志条目:

IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:1 Replace:0 XonLimit:1024 XoffLimit:1024 IOCTL_SERIAL_SET_HANDFLOW串行0成功摇动:1替换:0 XonLimit:1024 XoffLimit:1024

That seemed to prevent the framing error and the application seems to be working fine. 这似乎可以防止框架错误,并且该应用程序似乎运行正常。

Have you checked the settings for number of data bits, stop bits and parity? 您是否检查过数据位数,停止位和奇偶校验的设置?

The parity bit is a kind of error detection mechanism. 奇偶校验位是一种错误检测机制。 For instance: If you send using 7 data bits and one parity bit, the eighth bit will be used for detecting bit inversion errors. 例如:如果使用7个数据位和一个奇偶校验位进行发送,则第八个位将用于检测位反转错误。 If the receiver expects 8 data bits and no parity bits, the result will be garbled. 如果接收器需要8个数据位而没有奇偶校验位,则结果将出现乱码。

Unfortunately you did not mention exactly what type of differences you get. 不幸的是,您没有确切提及得到的区别类型。 Is it an occasional character that is different or is all your incoming data garbled ? 是偶尔出现的字符不同还是您输入的所有数据乱码? Note that characters read through the SerialPort.Read function could be changed by the system due to the setting of the SerialPort.Encoding property. 请注意,由于设置了SerialPort.Encoding属性,系统可能会更改通过SerialPort.Read函数读取的字符。 This setting affects the interpretation of the incoming text as it was text in ASCII, Unicode, UTF8 or any other coding scheme Windows uses for 'raw byte(s)' to 'readable text' conversion. 此设置会影响传入文本的解释,因为传入文本是ASCII,Unicode,UTF8或Windows用于“原始字节”到“可读文本”转换的任何其他编码方案的文本。

If you are reading into a byte array (ex: SerialPort.Read) you should get exactly the bytes you are seeing on PortMon. 如果您正在读取一个字节数组(例如:SerialPort.Read),则应该确切获得在PortMon上看到的字节。

If you are converting to characters (SerialPort.ReadLine or SerialPort.ReadChar) then the data will be encoded using the current encoding (SerialPort.Encoding property), which explains the differences you are seeing. 如果要转换为字符(SerialPort.ReadLine或SerialPort.ReadChar),则将使用当前编码(SerialPort.Encoding属性)对数据进行编码,这将说明您所看到的差异。

If you want to see characters with the same binary values as the bytes on the wire, a good encoding to use is Latin-1 as described in this post . 如果你想看到相同的二进制值电线上的字节字符,一个良好的编码使用的是拉丁语-1中描述的这个帖子

Example: 例:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM