- ベストアンサー
C# シリアル通信でデータ受信時の欠損について
- C#でシリアル通信を行っている際にデータ受信時に欠損が発生する問題が発生しています。
- SerialPort Classを使用してデータの送受信をするプログラムを作成していますが、非同期でデータを受信する際に正常にデータを取得できません。
- ReceivedBytesThresholdの値を変えることで一時的に問題を解決できましたが、期待するデータ量がわからない場合は使えない可能性があります。他の一般的な対処法について教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
DataReceivedイベントが発生したときでも、 シリアルポートへの受信はまだ継続している可能性があるので 不用意にバッファクリアしてはいけない。 非同期の受信処理は、何かと難しいのです。 private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { bytesRead = 0; // Initialize a buffer to hold the received data byte[] buffer = new byte[this.serialPort.ReadBufferSize]; try { //bytesRead = this.serialPort.Read(buffer, 0, buffer.Length); //if (true == serialPort.IsOpen) //{ // serialPort.DiscardInBuffer();//受信バッファをクリアする //} // 受信バッファにデータがなくなるまで繰り返し読込む while (true) { if (0 == serialPort.BytesToRead) { break; } buffer[bytesRead] = (byte)serialPort.ReadByte(); bytesRead++; System.Threading.Thread.Sleep(0); // シリアルポートの受信バッファには、 // ・必要なブロックの途中から受信している。 // ・次のブロックの先頭部分も受信されている。 // 可能性があるので、ここで必要なブロックだけRead()できたことを確認する。 if (必要なブロックが正常に読めたか確認する関数()) { break; } } } catch (Exception ex) { DataLog.Exception(ex); } //派生クラス用の処理 DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead); DeviceClassEvent(this, _DeviceClassEventArgs); }
その他の回答 (3)
- nak777r
- ベストアンサー率36% (49/136)
最初に _serialPort_DataReceived 関数で 5 Byte 読んで その後 _serialPort_DataReceived 関数で 40 Byte を読んだら、 途中からしか取れなかった。 関数の中には、「通信ポートを オープンしてるなら受信バッファをクリアする」 if (true == serialPort.IsOpen) { serialPort.DiscardInBuffer();//受信バッファをクリアする } という処理が入っているのですから当然そうなるのではないですか? 読込の関数を読んだ時点からデータの受信を開始するとした為、 それまで受信していたデータを捨ててまっさらな状態にする為 受信バッファをクリアしてるのですから そう考えれば解決方法は簡単で 受信バッファをクリアするの部分を受信バッファにある分、 全て別のバッファに読む様に修正して その別のバッファの中身を捨てるか、この後の本来の受信処理と つなげて処理するかを、通信フロー等を考慮しながら決めて 通信プログラムを作成します
お礼
>読込の関数を読んだ時点からデータの受信を開始するとした為、 それまで受信していたデータを捨ててまっさらな状態にする為 受信バッファをクリアしてるのですから なるほど。確かにそうですね。 なにが起こっているのかわからなかったのですがやっと理解出来ました。 ありがとうございます
- TooManyBugs
- ベストアンサー率27% (1472/5321)
一般的な対処法は意味を持ちません。 通信相手がどのような機器でどのようなデータをどのようなプロトコルで通信するのか、相手側のプログラムや設定を変更できるか等で全く変わってしまいます。
- koi1234
- ベストアンサー率53% (1866/3459)
>データが欠損してしまう理由、 >上記の対処法以外の一般的な対処法など有りましたら教えて下さい。 1.フロー制御を行う 2.ボーレートを下げる 等が一般的かと思います 場合によってはキャラクタ間にウエイト入れたり(これやると当然レスポンスは落ちます) 1を行うときは 信号線でのフロー制御を行う場合ケーブルも きちんと制御線に対応していることが条件となります キャラクタベースのフロー制御(XON/XOFF)はやり取りしてるデータによっては 使えない場合があります(バイナリデータやり取りする場合などは無理) とりあえず送信側でデータが落ちてるのか受信側で データ落ちしてるのかを確認するのが先ではないかと思います オーバランとかアンダーランとかのステータス確認してみてください あくまで参考までに
お礼
>不用意にバッファクリアしてはいけない。 なるほど。確かにそうですね。 なにが起こっているのかわからなかったのですがやっと理解出来ました。 ありがとうございます。