[英]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.