如何从c#中的serialPort读取完整的数据包数据

时间:2016-05-06 13:52:12

标签: c# .net serial-port

我正在实施SAS协议,其中记录了SAS将使用大小为11位的数据包进行轮询,其中一个起始位,八个数据位,第九个唤醒位和一个停止位。还记录了当SAS发送消息时,它为消息的第一个字节设置唤醒位,之后其他字节消息唤醒位清零。 我们还必须使用奇偶校验位作为唤醒位。

我面临从comport接收数据的问题。 我想要得到的数据是:

01 73 1D 00 09 03 00 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 B3 74 A4 02 0E 76

但我正在

73 1D 00 09 03 00 00 01 02 03 04 05 06

这里的第一个字节01没有进入收到的数据以及06之后的数据

bellow是用于创建串行端口对象的代码。

SerialPort _serialPort = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One);

当我写入Comport时,我将Parity设置为MARK。像:

  byte[] f = Response.ToArray();
  _serialPort.Parity = Parity.Mark;
  _serialPort.Write(f, 0, f.Length);

当我从comport阅读时

private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
 {
            SASobj._serialPort.ParityReplace = 0;

            SASobj._serialPort.Parity = Parity.Space;

            byte[] data = new byte[SASobj._serialPort.BytesToRead];
            SASobj._serialPort.Read(data, 0, data.Length);

            InputData = ByteToHex(data);

            this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });


        }

 private void SetText(string text)
        {

            this.txtMessage.Text += text;

        }

1 个答案:

答案 0 :(得分:1)

由于您的协议似乎滥用了奇偶校验位,因此您应该首先将<{1}}设置为零,然后再开始接收数据SerialPort.ParityReplace的实际值实际上是无关紧要的,因为您无论如何都会有一半的奇偶校验错误,但是在传入消息的中间更改这些属性肯定会产生问题。

但请注意,使用不同的事件SerialPort.ErrorReceived报告奇偶校验错误,其中一个参数设置为SerialError.RXParity

另外,正如我在评论中指出的那样,调用SerialPort.Parity并不是一个好主意,因为它将方法调用排在后台(BeginInvoke)线程上,这意味着多次调用{ {1}}发生的事情不一定是顺序的。

正如@Gusman建议的那样,有更好的方法从端口获取数据,但确保您获得有序合并的最简单方法是:

ThreadPool

此外,SerialPort.ErrorReceived的MSDN文档有关于rx奇偶校验错误的评论:

  

如果流的尾随字节发生奇偶校验错误,则会在输入缓冲区中添加一个额外字节,值为126.

我认为这意味着SetText内的值readonly object _lock = new object(); SerialPort _serialPort; string _text = ""; public void Init() { _serialPort = new SerialPort("COM1", 19200, Parity.Space, 8, StopBits.One); _serialPort.ParityReplace = 0; _serialPort.DataReceived += DataReceived; _serialPort.ErrorReceived += ErrorReceived; _serialPort.Open(); } void DataReceived(object sender, SerialDataReceivedEventArgs e) { DumpToHexString(); } void ErrorReceived(object sender, SerialErrorReceivedEventArgs e) { if (e.EventType == SerialError.RXParity) DumpToHexString(); } void DumpToHexString() { lock (_lock) { while (_serialPort.BytesToRead > 0) { var chunk = new byte[_serialPort.BytesToRead]; _serialPort.Read(chunk, 0, chunk.Length); _text += ByteToHex(chunk); } } this.BeginInvoke(new Action(() => txtMessage.Text = _text)); } 的尾随字节应该被丢弃,但我实际上并没有这样一个特定的情况,所以你可能想检查一下确实如此。