
Visualstudio 2013 を使用して C# で開発を行っています。
SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、
非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。
5Byteのデータは正常に取得できるのですが、
その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。
serialPort.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();//受信バッファをクリアする
}
}
catch (Exception ex)
{
DataLog.Exception(ex);
}
//派生クラス用の処理
DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead);
DeviceClassEvent(this, _DeviceClassEventArgs);
}
--------------------------------------------------------------------------------------
ネットの情報を参考に、
ReceivedBytesThreshold の値を期待するデータ量に逐一変えることで
とりあえず正常に取ることが出来たのですが、これでいいのでしょうか?
期待するデータ量がわからなかった場合は使えないのかなとも思います。
データが欠損してしまう理由、
上記の対処法以外の一般的な対処法など有りましたら教えて下さい。
その他参考になるページ等ありましたら教えていただけると大変助かります。
No.3ベストアンサー
- 回答日時:
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);
}
>不用意にバッファクリアしてはいけない。
なるほど。確かにそうですね。
なにが起こっているのかわからなかったのですがやっと理解出来ました。
ありがとうございます。
No.4
- 回答日時:
最初に _serialPort_DataReceived 関数で 5 Byte 読んで
その後 _serialPort_DataReceived 関数で 40 Byte を読んだら、
途中からしか取れなかった。 関数の中には、「通信ポートを
オープンしてるなら受信バッファをクリアする」
if (true == serialPort.IsOpen)
{
serialPort.DiscardInBuffer();//受信バッファをクリアする
}
という処理が入っているのですから当然そうなるのではないですか?
読込の関数を読んだ時点からデータの受信を開始するとした為、
それまで受信していたデータを捨ててまっさらな状態にする為
受信バッファをクリアしてるのですから
そう考えれば解決方法は簡単で
受信バッファをクリアするの部分を受信バッファにある分、
全て別のバッファに読む様に修正して
その別のバッファの中身を捨てるか、この後の本来の受信処理と
つなげて処理するかを、通信フロー等を考慮しながら決めて
通信プログラムを作成します
>読込の関数を読んだ時点からデータの受信を開始するとした為、
それまで受信していたデータを捨ててまっさらな状態にする為
受信バッファをクリアしてるのですから
なるほど。確かにそうですね。
なにが起こっているのかわからなかったのですがやっと理解出来ました。
ありがとうございます
No.2
- 回答日時:
一般的な対処法は意味を持ちません。
通信相手がどのような機器でどのようなデータをどのようなプロトコルで通信するのか、相手側のプログラムや設定を変更できるか等で全く変わってしまいます。
No.1
- 回答日時:
>データが欠損してしまう理由、
>上記の対処法以外の一般的な対処法など有りましたら教えて下さい。
1.フロー制御を行う
2.ボーレートを下げる 等が一般的かと思います
場合によってはキャラクタ間にウエイト入れたり(これやると当然レスポンスは落ちます)
1を行うときは
信号線でのフロー制御を行う場合ケーブルも
きちんと制御線に対応していることが条件となります
キャラクタベースのフロー制御(XON/XOFF)はやり取りしてるデータによっては
使えない場合があります(バイナリデータやり取りする場合などは無理)
とりあえず送信側でデータが落ちてるのか受信側で
データ落ちしてるのかを確認するのが先ではないかと思います
オーバランとかアンダーランとかのステータス確認してみてください
あくまで参考までに
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- その他(データベース) c言語の問題です。これを踏まえてコーディングしたいのでおしえていただきたいです。 3 2023/08/03 09:27
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Excel(エクセル) CSVファイルがカンマ区切りにならない。対処法を教えていただきたいです。 仕事でSMS一斉送信ができ 2 2022/07/01 21:24
このQ&Aを見た人はこんなQ&Aも見ています
-
シリアル通信の出力バッファと送信完了イベントについて
C言語・C++・C#
-
SerialPortのDataReceivedイベントについて
Visual Basic(VBA)
-
ManagementClassが見つからない。
C言語・C++・C#
-
-
4
Linuxでのシリアル通信についてですが、受信のときにデータがずれた状態で送られてくることがあります
C言語・C++・C#
-
5
C#のシリアル通信プログラムで文字化け
C言語・C++・C#
-
6
FORMが開いているかどうかの確認方法
Visual Basic(VBA)
-
7
VB.netで、シリアル通信のタイムアウト処理について
Visual Basic(VBA)
-
8
CloseとDisposeの違い
Visual Basic(VBA)
-
9
別のフォームで記述している関数を実行するには?C#
C言語・C++・C#
-
10
シリアル通信の受信待ちについて
C言語・C++・C#
-
11
シリアル通信でのデータ取りこぼし
Visual Basic(VBA)
-
12
C# ソケット通信でデータ受信時の欠損について
C言語・C++・C#
-
13
シリアル通信でのデータ受信
C言語・C++・C#
-
14
シリアル通信 大きいサイズの受信処理
C言語・C++・C#
-
15
RS232Cケーブル ストレートとクロスを見分ける方法
その他(パソコン・周辺機器)
-
16
COMポートの同時オープン同時読み込み
C言語・C++・C#
-
17
C#でフォームのオブジェクト名を変数名で指定
C言語・C++・C#
-
18
C#にてCTI。RS232Cの受信と送信について。
その他(プログラミング・Web制作)
-
19
C#で通信処理。応答がない場合、すぐエラーにしたい
その他(プログラミング・Web制作)
-
20
VB.NET(2005)のSerialPort" RTSラインを制御"
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
ウインドウズメディアプレイヤ...
-
PDAのシリアルポートデータの消去
-
writeで止まります
-
visual c# 2010 シリアル通信ア...
-
winsockの動作について。
-
FormatMessageでのバッファサイ...
-
socket: recvはいつ,どれだけ...
-
シリアル通信の出力バッファと...
-
ソケット通信内 read関数について
-
シリアル通信エラー
-
winsockでソケット通信の開発を...
-
WinsockAPIのrecvfromの受信デ...
-
SerialPortのDataReceivedイベ...
-
Macターミナルで実行中のプログ...
-
メモリのセグメント違反の解決...
-
TCP/IP通信時のサーバーからの受信
-
バックグラウンドのプロセスの...
-
HTMLからJava
-
チェックボックスの周囲の色が
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
「スイッチングハブのバッファ...
-
winsockでソケット通信の開発を...
-
シリアル通信の出力バッファと...
-
WriteFile()でのデータ送信がで...
-
Linuxでのシリアル通信について...
-
WinsockAPIのrecvfromの受信デ...
-
socket: recvはいつ,どれだけ...
-
SerialPortのDataReceivedイベ...
-
ClearCommError呼び出し時のCE_...
-
TCPでの非同期型select関数につ...
-
シリアルポート通信
-
シリアル通信 大きいサイズの...
-
winsockの動作について。
-
ソケット通信内 read関数について
-
COMポートの同時オープン同時読...
-
SocketのSend関数でのCLOSEの検...
-
waveIn、waveOutでの音声録音・...
-
write関数でEAGAINのエラー発生...
-
rs232cでの受信データ(mscomm)...
おすすめ情報