1

シリアル接続を介して長距離無線から入力を受信するアプリケーションを作成しています。現在、SerialPort C# クラスを使用してデータを送受信していますが、いくつか問題があります。データを受信するための関数がバッファ バイト配列サイズを正しく設定していないことに気付きました。すべてのデータはバイトコード (16 進数) で送信されます。

他のノードが 103 バイトのデータを送信するとします。コードをステップ実行し、「Read()」行にブレークポイントを設定すると、「serialPort1.BytesToRead-1」が 103 に評価されることがわかりますが、byte[] 配列は 17 にしか初期化されません。この動作については説明がありません。 . その結果、最初の 17 バイトだけが配列に入れられます。ステップ スルーを続けると、この同じイベントがトリガーされます。今回は "serialPort1.BytesToRead-1" が 85 に評価されます (おそらく、103 バイトのうち最初の 17 バイトだけが読み取られたためです。

データ配列のサイズを 103 にハードコアすると、1 回のパスで問題なく動作します。ただし、現時点では、バイト配列のすべてのデータを 1 回のパスで格納することができず、多くの問題が発生しています。私のバイト配列がこのような任意のサイズに初期化されている理由を知っている人はいますか???

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
        byte[] data = new byte[serialPort1.BytesToRead - 1];
        serialPort1.Read(data, 0, data.Length);
        DisplayData(ByteToHex(data) /*+ "\n"*/);
}

更新:これが私が試みている新しい方法です。isHeader は、最初に true に設定されたブール値です (パケットから受信される最初の 2 バイトが実際にはパケットの長さであるため)。

    const int NUM_HEADER_BYTES = 2;

    private void serialPort1_DataReceived(object sender,                     System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        byte[] headerdata = new byte[2];
        if (isHeader)
        {
            serialPort1.Read(headerdata, 0, NUM_HEADER_BYTES);
            int totalSize = (headerdata[0] << 8 | headerdata[1]) >> 6;
            serialPort1.ReceivedBytesThreshold = totalSize - NUM_HEADER_BYTES;
            data = new byte[totalSize - NUM_HEADER_BYTES];
            isHeader = false;
        }
        else
        {
            serialPort1.Read(data, 0, data.Length);
            double[][] results = ParseData(data, data.Length);
            serialPort1.ReceivedBytesThreshold = NUM_HEADER_BYTES;
            isHeader = true;
            DisplayData(ByteToHex(data) /*+ "\n"*/);
        }
    }
4

2 に答える 2

3

BytesToRead は、バッファーで待機しているバイト数と同じです。新しいデータが到着すると、刻々と変化します。それがここに表示されているものです。

デバッガーをステップ実行すると、追加の時間がかかり、デバッガーをステップ実行している間に残りのシリアル データが読み込まれるため、BytesToRead は完全な値の 104 に変更されます。

103 バイトが必要であることがわかっている場合は、ReceivedBytesThresholdを 104 に設定すると、適切なタイミングで DataRecieved イベントがトリガーされると思います。受信する必要があるメッセージのサイズがわからない場合は、別のことを行う必要があります。1 バイト (serialPort1.BytesToRead - 1 ) を捨てていることに気付きましたが、データを読み取るときに検索できるメッセージの終わりのバイトですか?

于 2012-11-06T23:01:45.320 に答える
2

リアルタイムのデータ転送に関しては、デバッガーは提供しません。デバッグ トレースを使用します。

ところで、イベントに信頼を置くのではなく、自分でデータをポーリングします。シリアル ポートを使用する場合、これは健全で信頼性の高いアプローチです。

コメントごとに編集: シリアル データ転送速度は、ボーレートによって制限されます。データの損失が心配なので、数値を見てみましょう。

仮定:

baud_rate = 19600 [bytes/sec]  // it's usually *bits*, but we want to err upwards
buffer_size = 4096 [bytes]     // windows allocated default buffer size

したがって、次のものが必要です。

4096/19600 [sec] ~ 200 [ms]

バッファをオーバーフローさせる (上限)。

したがって、 でサンプリングする場合50 Hz、1 桁のセーフティ ネットで実行されていることになります。これは適切な場所です。各「サンプル」で、バッファ全体を読み取ります。ここにはタイミングの問題はありません。

もちろん、あなたのケースに合わせて数値を採用する必要がありますが、低帯域幅の RF チャネルが50 Hz十分なオーバーキルではない転送速度になるとしたら、私は驚かれることでしょう。

最後の編集: 言うまでもなく、現在持っているものが機能する場合は、触れないでください

于 2012-11-06T23:23:56.023 に答える