需要 .NET 串行端口帮助,主要涉及在多个“数据包”中接收的数据

StackOverflow https://stackoverflow.com/questions/891475

  •  23-08-2019
  •  | 
  •  

我对通过 .net 通过串行端口发送数据非常陌生,并且在实现 TCP 对应项后我注意到我不会用串行那么容易地得到它!

因此,从顶部开始,我几乎已经实现了串行双向通信实现,但我只是陷入了一些问题:-

  1. 我的读取被分成多条消息,或者通过 COM 端口作为碎片响应接收,我不知道我可能需要什么设置,或者我应该如何以不同的方式编写代码来解决这个问题。什么可能导致这种情况?我正在断点处检查消息 SerialPort_DataReceived.

基本上数据应该发送为:

01: LS|DA090521|TI111043|q
02: PS|RN102|PTC|TA1040000|P#0|DA090521|TI111429|j

但它正在被分割(在每个请求读取的随机位置)

01: LS|DA090521|TI111
02: 043|q
03: PS|RN102|PTC|TA1
04: 0000|P#0|DA090521|TI111429|j

- 问题 1 已得到解答,谢谢 Chris W.和别的!我现在有了我期望从片段逐步构建的消息(寻找 STX、{msg body}、ETX),然后在消息完全构建时执行一个操作,并使用线程安全队列让它继续运行,非常高兴。

. 。2.我几乎每个周期都会在读取过程中收到一个“|”符号,这是由于我以某种方式设置了错误的命令、串行通信的伪影,还是设备发送给我的东西?(但我不这么认为,因为超级终端连接显示该字符没有被连续发送。)

。3.您能否确认我在相应的方法中正确读取和写入数据?

也谢谢大家看我的另外两个问题。

相关代码如下:

...
    //                          COM3,    9600,     None,   8,        One
    SerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBits);
    if (SerialPort.IsOpen) SerialPort.Close();
    // SerialPort.RtsEnable = true; // Request-to-send
    // SerialPort.DtrEnable = true; // Data-terminal-ready
    SerialPort.ReadTimeout = 150; // tried this, but didn't help
    SerialPort.WriteTimeout = 150; // tried this, but didn't help
    SerialPort.Open();

    SerialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
}

void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // Process received data
    SerialPort sp = (SerialPort)sender;
    byte[] buffer = new byte[sp.BytesToRead];
    int bytesRead = sp.Read(buffer, 0, buffer.Length);

    // message has successfully been received
    message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
}

public bool SendMessage(string text)
{
    // Only send message if a client is connected
    if (SerialPort != null && SerialPort.IsOpen)
    {
        byte[] buffer = Encoding.ASCII.GetBytes(text);
        SerialPort.Write(buffer, 0, buffer.Length);
    }
}
有帮助吗?

解决方案

我的阅读内容被分成多条消息

这是正常的、预期的、不可避免的行为。TCP 数据传输也可能发生这种情况。对于串行接口来说,它只是无尽的字节流。您的应用程序有责任将这些字节重新打包成数据包。

如果数据包边界的位置很重要,并且如果您无法通过查看接收到的数据来判断数据包边界应该在哪里,那么您可能需要重新考虑数据的格式,以便您可以 告诉数据包边界在哪里。

我几乎每个周期都会在阅读过程中收到一个“|”符号

该字符的十六进制值是多少?查看是否设置了 Handshake 财产给 XOnXOff 或者 RequestToSendXOnXOff 改善情况。

其他提示

在较低级别,串行端口可以决定何时触发数据接收事件。它可能决定在“完整”数据包到达之前执行此操作。但是,您的预期数据集中似乎有一个终止符字符。如果是这样,您可以执行以下操作(请注意,我已更改您的 SerialPort 分配以避免语法混乱:

        p = new SerialPort(PortName, BaudRate, Prty, DataBits, SBits);
        p.NewLine = Terminator;

其中 Terminator 是包含终止字符的字符串。然后您可以使用 SerialPort.ReadLine() (和 SerialPort.WriteLine() 如果适用)。这至少可能有助于解决您的第一个问题。

我已经完成了大量的 Win32 串行端口编程,但只使用了一点 .NET,所以请对我的建议持保留态度。

我的读取被分成多条消息,或者通过 COM 端口作为碎片响应接收,我不知道我可能需要什么设置,或者我应该如何以不同的方式编写代码来解决这个问题。

正如其他人所说,这是完全正常的。根据 DCE 端的设备类型,您可能需要自行重新包装。我不确定你连接的是哪种类型的设备,所以我不能说更多。

如果您想获取更多数据,可以尝试以下操作:

  • 调整 System.Int32 ReceivedBytesThreshold 属性
  • 使用同步 I/O 并指定要读取的固定字节数,而不是基于事件的接收

我几乎每个周期都会收到一个“|”符号,是 这是由于我设置的命令 不知何故,错误地,串行的工件 通信,或设备的东西 送我来吗?(我不这么认为 虽然,作为超级终端连接 揭示这个角色不是 连续发送。

如果您对线路上发生的事情感到好奇,请查看 来自 SysInternals 的 PortMon, ,一个免费的应用程序,可以在您通过线路传输数据时监听您的 com 端口。这看起来很技术性,但实际上您只需要查看 IRP_MJ_WRITE 和 IRP_MJ_READ 命令,您就会在线上看到以字节为单位的长度以及通过线路发送的数据。这样,您应该能够判断问题是否出在 .NET SerialPort 对象上,或者设备是否实际通过线路发送“|”。

你能确认我正在阅读吗? 在 各自的方法。

它看起来适合基于事件的数据接收方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top