簡體   English   中英

如何在C#中從SerialPort讀取完整的數據包數據

[英]How to read full packet data from serialPort in c#

我正在實現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之后的數據

下面是用於創建串行端口對象的代碼。

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

當我寫信給Comport時,我將奇偶校驗設置為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;

        }

由於您的協議似乎正在濫用奇偶校驗位,因此應開始接收數據之前首先將SerialPort.ParityReplace設置為零。 那么, SerialPort.Parity實際值實際上是無關緊要的,因為無論如何您都會有一半的時間遇到​​奇偶校驗錯誤,但是在傳入消息的中間更改這些屬性肯定會造成問題。

但是,請注意,奇偶校驗錯誤是通過另一個事件( SerialPort.ErrorReceived ,其中一個參數設置為SerialError.RXParity

另外,正如我在評論中指出的那樣,調用BeginInvoke並不是一個好主意,因為它將方法調用在后台線程( ThreadPool )上排隊,這意味着對SetText多次調用發生的順序不必是順序的。

正如@Gusman所建議的那樣,有一些更好的方法可以從端口獲取數據,但是確保獲得有序合並的最簡單方法是:

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));
}

此外,針對SerialPort.ErrorReceived的 MSDN文檔中有關於rx奇偶校驗錯誤的說明:

如果流的尾部字節發生奇偶校驗錯誤,則會將額外的字節添加到輸入緩沖區,其值為126。

我以為這意味着應該丟棄ErrorReceived內的值126的尾隨字節,但是我實際上沒有這種特殊情況,因此您可能要檢查是否確實如此。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM