• 締切済み

SerialPortのDataReceivedイベントについて

Visial Basic 2005 にて SerialPort コンポーネントを使ったアプリを作っています。 当初、Microsoft のサンプルを参考に SerialPort1.ReadLine でデータを受信していたのですが、この方法だとバッファ内から再度同じデータを受信してしまうらしく、新しいバッファからデータを受信しないとイベントが発生する毎に古いデータを読み取ってしまいます。 そこで調べていたところ、Microsoft のフォーラムで以下のような Visual C# のソースを見つけました。 (以下引用) > if (serialPort1.BytesToRead > 0) > { > // 受信バッファからデータを取得 > byte[] b = new byte[serialPort1.BytesToRead]; > Read(b, 0, b.Length); > } まだ Visial Basic 初心者なもので Byte 型の扱い方や上記ソースは Visial Basic でどのように書けばよいのかわかりません。 どなたかご教授ください。 よろしくお願いいたします。

みんなの回答

  • miyuyu
  • ベストアンサー率61% (30/49)
回答No.1

こんにちは、もう解決しているかもしれませんが。 ReadLineのヘルプには、 入力バッファ内の NewLine 値まで読み取ります と記載してあります。Framework2.0からの機能なんですね。 私の場合、データ受信後その内容により返事を返すまでの間 次のデータを受信することは無い場合が多いので DataReceivedイベントでSerialPort.Readを利用しています。 ReadLineは使用したことが無いのでわかりませんが Readの場合、読み込んだデータがバッファに残っているということはありません。

ikspiari
質問者

お礼

SerialPort.ReadLine を使っても、SerialPort.DiscardInBuffer でバッファを削除したら問題なく動作しました。 ありがとうございました。

ikspiari
質問者

補足

アドバイスありがとうございます。 今のところまだ未解決なのですが、私も miyuyu さんと同じようにデータ受信の内容に応じて返事をするというものを作っています。 問題となっている現象は、二度目のデータ受信時の DataReceived イベント発生の際に一度目に送った返事を即送り出してしまうという感じです。 Write の方のバッファもあやしい気がするのですが、差し支えなければ Read の使い方を教えていただけますと幸いです。 よろしくお願いします。

関連するQ&A

  • VB2010 COMポートからのバイナリ受信

    オシロスコープからの画像データ(40kバイト程度のtifファイル)をPCのCOMポートから受信し 保存するプログラムを作成しているのですが、受信データを正しくPC上に保存できません。 具体的には下記のコードでtifファイルは作成されますが、容量が数kバイトで明らかに不足 しています。 MsgBoxを有効にして受信バッファサイズや書込み長さを確認しましたが、「OK」ボタンを押す たびに下記の表示になります。COMポートのバッファサイズが4096バイトなので「dat.Length」 をすべて足し合わせると本来の受信データサイズになると思うのですが、PC上に作成された ファイル容量から「dat」が常に上書きされているような気がします。 正しく保存するにはどのような修正が必要でしょうか? 【MsgBoxを有効にしたときの表示値(OKを押すたびに数値が変わる)】 「dat.Length」 183 4075 4072 4092 4088 4084 4085 4092 4059 4078 3910 0 0 ・ ・ ・ 「ByteToRead」 4060 1508 324 908 2334 1785 70 227 400 0 0 ・ ・ ・ 【作成したコード】 Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As_ System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived ' シリアルポートからデータ受信 Dim dat As Byte() = New Byte(SerialPort1.BytesToRead - 1) {} SerialPort1.Read(dat, 0, dat.GetLength(0)) 'MessageBox.Show(dat.Length) 'MessageBox.Show(SerialPort1.BytesToRead) File.WriteAllBytes("C:\test1.tif", dat) SerialPort1.DiscardInBuffer() End Sub 【環境】 OS:Win7 VB:2010 ポート設定:SerialPortクラス標準からポート番号以外は変更なし

  • C# シリアル通信でデータ受信時の欠損について

    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 の値を期待するデータ量に逐一変えることで とりあえず正常に取ることが出来たのですが、これでいいのでしょうか? 期待するデータ量がわからなかった場合は使えないのかなとも思います。 データが欠損してしまう理由、 上記の対処法以外の一般的な対処法など有りましたら教えて下さい。 その他参考になるページ等ありましたら教えていただけると大変助かります。

  • VisuaBasic SerialPort

    SerialPortを使用してRS232Cアプリケーション(9600bpsフロー制御無し)を作成しました。 ハードをUSB接続しては送信受信共に問題無く動作しています。 ハードをUSB未接続で送信データを入力して送信すると大抵の場合にフリーズします。 フリーズしない場合でも2回目を送信すると確実にフリーズします。 フリーズの原因やその対策方法をご存知でしたら教えて頂きたく。 よろしくお願い致します。 (Windows10、Microsoft Visual Basic 2010 Express を使用)

  • javaのソケット通信の受信で、InputStreamの終了が認識出来

    javaのソケット通信の受信で、InputStreamの終了が認識出来ません。 (1)下記のネット上で見つけたチャットクライアントのソース"ChatClient.java"を流用しました。  http://www.saturn.dti.ne.jp/~npaka/android/SocketEx/index.html  チャットサーバもこのサイトのソースを実装しました。この組み合わせで送受信は確認しました。 (2)これを下記のjavaのオープンソースを実装して、バイト読み出しに変更しました。  ・上記の元のソースの受信ループ中の読み出し部   size=in.read(w); → size=readsocket(w);  【"java\io\InputStream.java"より】   public int read(byte b[]) throws IOException {  //※1     return read(b, 0, b.length);      //※2   }   public int readsocket2(byte b[], int off, int len) throws IOException {//※3     if (b == null) {       throw new NullPointerException();     } else if ((off < 0) || (off > b.length) || (len < 0) ||         ((off + len) > b.length) || ((off + len) < 0)) {       throw new IndexOutOfBoundsException();     } else if (len == 0) {       return 0;     }     int c = read();    //※4     if (c == -1) {       return -1;     }     b[off] = (byte)c;     int i = 1;     try {       for (; i < len ; i++) {       c = in.read();       if (c == -1) {         break;       }       if (b != null) {         b[off + i] = (byte)c;       }       }     } catch (IOException ee) {     }     return i;   } ・上記の名前の付け替え   ※1:public int readsocket(byte b[]) throws IOException {   ※2:return readsocket2(b, 0, b.length);   ※3:public int readsocket2(byte b[], int off, int len) throws IOException {   ※4:int c = in.read(); (3)この変更を行うと、“in.read()”でストリームの終了の"-1"が入って来ず、forループから抜けなくなってしまいました。帰って来るのは送信したコードのみです。どこが悪いのでしょうか?

    • ベストアンサー
    • Java
  • ソケット通信の受信で、InputStreamの終了が認識出来ません。

    ソケット通信の受信で、InputStreamの終了が認識出来ません。 (1)下記のネット上で見つけたチャットクライアントのソース"ChatClient.java"を流用しました。  http://www.saturn.dti.ne.jp/~npaka/android/SocketEx/index.html (2000文字を超えるので掲載出来ません)  チャットサーバもこのサイトのソースを実装しました。この組み合わせで送受信は確認しました。 (2)これに下記のjavaのオープンソースを実装して、バイト読み出しに変更します。  【"java\io\InputStream.java"より】   public int read(byte b[]) throws IOException {  //※1     return read(b, 0, b.length);      //※2   }   public int read(byte b[], int off, int len) throws IOException {//※3     if (b == null) {       throw new NullPointerException();     } else if ((off < 0) || (off > b.length) || (len < 0) ||         ((off + len) > b.length) || ((off + len) < 0)) {       throw new IndexOutOfBoundsException();     } else if (len == 0) {       return 0;     }     int c = read();    //※4     if (c == -1) {       return -1;     }     b[off] = (byte)c;     int i = 1;     try {       for (; i < len ; i++) {       c = in.read();       if (c == -1) {         break;       }       if (b != null) {         b[off + i] = (byte)c;       }       }     } catch (IOException ee) {     }     return i;   }  ・リンク先のソース中の入力ストリーム読み出し部の名前の付け替え  size=in.read(w); → size=readsocket(w);  ・javaのオープンソース"java\io\InputStream.java"中の名前の付け替え   ※1:public int readsocket(byte b[]) throws IOException {   ※2:return readsocket2(b, 0, b.length);   ※3:public int readsocket2(byte b[], int off, int len) throws IOException {   ※4:int c = in.read(); (3)この変更を行うと、※4の“in.read()”で入力ストリームの終了の"-1"が入って来ず、forループから抜けなくなってしまいました。帰って来るのは送信したコードのみです。どこが悪いのでしょうか?

    • ベストアンサー
    • Java
  • C#でtrimができません

    VisualC#2010開発での質問です。 byte[] b = new byte[1024]; stream.Read(b, 0, b.Length); string s= Encoding.ASCII.GetString(b); とやったあとの文字列sの末尾空白がtrimできません。 どうやればよいのでしょうか?

  • VBでシリアル通信がうまくいきません

    VisualBasicのシリアルポートメソッドを使い、RS232-C通信を試そうとしている初心者です。 現在、別のPCからTeratermより文字を送り、自分のPCで受信結果を得ようとしているのですが 別PCから単発で文字を送っても、自分のPCでは反応せず キーボードを押しっぱなしにすると、自分のPCのウィンドウに受信結果が表示されます。 一体、何が原因なのでしょうか? さっぱり、わからず途方に暮れています。 下記にソースコードを記載しますので、詳しい方は教えて下さると幸いです。 ------------------------------------------------------------------------ Public Delegate Sub MyDelegate(ByVal intData As Integer) Private Sub AddData(ByVal str As String) TextBox1.Text = str End Sub Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Dim dlgByte As MyDelegate = New MyDelegate(AddressOf AddData) Dim ByteRead(SerialPort1.BytesToRead - 1) As Byte SerialPort1.Read(ByteRead, 0, SerialPort1.BytesToRead) For i As Integer = 0 To ByteRead.Length - 1    Me.Invoke(dlgByte, ByteRead(0)) Next End Sub ------------------------------------------------------------------------

  • Readメソッドが次の行に処理を渡すタイミング

    C#ですが、Readメソッドを使ってバイト配列を 読み込むとき、次の処理に移るタイミングが よく分かりません(ソケットからデータを受ける時)。 例えば、JAVAなどのreadLine()などは、改行や、 EOFで、次の行に移ります。 Readは、このような、区切りが無いのでよく分かり ません。 0バイトで移るのかとも思いましたが、受信バイト数 を数えると、文字数以上のバイトはいっさい受信 されていないので、送信側で、自動で0バイトを つけているようでもありません。 それでも送信側で文字を送ると、その送信単位で 次の処理に移ってくれています。 送信から次の送信までの区切りは何で認識して いるのでしょうか(区切りがない以上、受信バッファ がいっぱいになるまで、待ってもよさそうですが)。 なにか分かる人がいましたらお願いします。

  • vb2005で受信関数を以下の作成しています。

    vb2005で受信関数を以下の作成しています。 Private Sub r_SerialPort1_DataReceived(ByVal sender As Object, _  ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _  Handles SerialPort1.DataReceived  Dim tmp As Integer  Try   tmp = SerialPort1.BytesToRead '受信バイト数取得 SerialPort1.Read(s_RxBuff, s_RxCont, tmp) 'データ読込み s_RxCont = s_RxCont + tmp '受信バイト数更新  Catch ex As Exception s_Status = c_ErrTRP 'ポートエラー(受信) End Try End Sub この関数で割込みが入るのですが、tmp=の所でbreakし読出そうとしてSerialPort1をウォッチすると、 "ポートは閉じられています"と表示されていて、Catch方向に進むのですが、何故こんなことが起こるのでしょうか? 宜しくお願いします。

  • Javaアプリでデバイスファイルを制御

    SDIOインターフェイスにより接続されたSDIOホスト機器とSDIOデバイス機器との間で、SDIOホスト機器上で動作するJava swingアプリから、SDIOデバイス機器へ、通信試験をしています。SDIOホスト上で動作環境は以下の通りです。 OS:Ubuntu 12.10 server Java:version7 ホスト上で動作するSDIOデバイス機器用のデバイスドライバ:ttyドライバ 以下のプログラムでwriteは正常に動くのですが、readが実行されません。 ttyドライバは、デバイスファイルとして、別の場所にてFile file = new File("/dev/ttyPontos0;で宣言しています。reaed関数のin.available();の戻り値は、0が変えてきてしまいreadできないという状態です。お気付きの点ありましたら、大変ありがたいです。宜しくお願い致します。 public void actionPerformed(ActionEvent event) {   int i,rev_bytes; if(event.getActionCommand().equals("register_read")) { char[] cmd1 = {'s','h','o','w',' ','r','e','g',' ','-','r',' ','0','x',/*11*/'0','0','4','0','5','4','A','0','\r'}; byte[] txdata = new byte[cmd1.length]; byte[] rxdata = new byte[126];          for(i=0;i<cmd1.length;i++) { txdata[i]=(byte)cmd1[i]; } logfild.setText("register_read\n");     send_byte2(txdata,cmd1.length);/*byte列を送信*/ }else if(event.getActionCommand().equals("register_write_all")) { byte[] rxdata = new byte[126];        logfild.setText("receive\n");     rev_bytes=receive2(rxdata); String f = new String(rxdata); logfild.setText("rxdata=\n"+ f); } } public void send_byte2(byte[] senddata,int length) { try {       /*fileは別の場所で宣言しています*/ out = new FileOutputStream(file); out.write(senddata); out.close();/*書込み終了*/ logfild.append("\nFileOutputStream1_success\n"); } catch (IOException e) { // TODO 自動生成された catch ブロック logfild.append("FileOutputStream1_fail\n"); e.printStackTrace(); } } /*バッファにあるだけ受信する*/ public int receive2(byte[] receive) { int Bytes=0,num; try {        /*fileは別の場所で宣言しています*/ FileInputStream in = new FileInputStream(file); num=in.available();//read可能なバイト数を返す logfild.append("read_num\n"+num); Bytes=in.read(receive); in.close(); } catch (IOException e) { logfild.append("read_fail\n"); e.printStackTrace(); } return Bytes; }

専門家に質問してみよう