.NETのシリアルポートの送信で困っています

このQ&Aのポイント
  • WindowsXP、C#、.NET Framework 2.0の環境で、rs232cを使用してデータを別のPCのアプリと送受信するプログラムを作成しています。
  • System.IO.Ports.SerialPort クラスを使用しており、通常は問題なく送受信できます。しかし、10240バイトのデータを送信すると受信側が4096バイトしか受信できません。
  • SerialPort.Writeメソッドで送信し、WriteBufferSizeとReadBufferSizeの設定も変更していますが、問題の解決には至っていません。設定を変更するべき箇所があるのか、教えていただけませんか?
回答を見る
  • ベストアンサー

.NETのシリアルポートの送信で困っています

環境はwindowsXP、C#、.NET Framework 2.0です。 rs232cを使ってデータを別のPCのアプリ(windowsXP、C)と送受信するプログラムを 作っています。 System.IO.Ports.SerialPort クラスを使用しており、 通常は問題なく送受信できます。でも、送信するデータを 10240バイト(10キロバイト)にすると受信側が4096バイトしか受信できません。 SerialPort.Write (Byte[10240], 0, 10240) で送信し、 WriteBufferSizeは1024×11に設定しています。(関係ないかも しれませんがReadBufferSizeも10240以上に設定 ) 送受信データを監視する別ツールで確認しても、送信側が4096しか 送れていないです。 他に設定を変更すべき所があるのでしょうか?要因が分からず 困っています。ご教授ください。

質問者が選んだベストアンサー

  • ベストアンサー
noname#214300
noname#214300
回答No.1

外れてるかも知れませんが、シリアルのバッファは10kバイトも取れなかったと思います。 4096バイトずつ受信するようにプログラムを変更されてはいかがでしょうか。 (自分は以前、シリアルで1024バイトずつ受信して、別に用意した大きいバッファに逐次溜めていき、一連のデータストリームを再現するようなプログラムを組んだことはあります)

Kafka_F
質問者

補足

>シリアルのバッファは10kバイトも取れなかった 実は受信側のプログラムは10kを受信できている実績があるそうです。 仰せの通り、受信側のプログラムはシリアルポートの特性で分割してデータが送られることを想定して全データがそろうまでためている作りになっているとのことでした。 そうすると、送信側もデータ量が多い時は、プログラムで意図的に分割して送ればいいのかもしれないですね。ヒントを与えて下さってありがとうございます!試してみます。

その他の回答 (1)

回答No.2

Write () メソッドを実行した後すぐにClose() してませんか? 10kバイトのデータを送信し終わるにはそれなりの時間がかかります。(9600ボーの場合で約10秒) Close() を実行すると途中でも送信を中断します。

Kafka_F
質問者

補足

いいえ、closeはユーザが画面から切断するボタンを押下しない限り、closeしないようにしています。DataReceived を利用して、常に送受信をタイムリーに行うような作りにしています。

関連するQ&A

  • 計測用データを送信するには

    帯域測定プログラムを作っています。 まず送信側で通信に使用するデータサイズを決めて受信側に送信し、 そのデータを使って互いに送受信して帯域測定を行いたいです。 送信側で50000バイトのデータを使って計測を使用と決めて、50000バイトという情報を受信側に送信します。 int data = 50000; String unit = "byte"; byte[] send_size = (data+unit).getBytes(); out.write(send_size); out.flush(); これを受信側は受け取り50000バイトという数値に変換したいのですが、 変換の仕方が分かりません。 バイトに変換して送信しているので、5は53に、0は48に変換されているので、53->5、48->0というように変換してやりたいのですが、 どうすればよいのでしょうか? また、50000バイトという情報を相手側にもっと賢く遅れる方法があればそちらについてのアドバイスも頂きたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • シリアル通信(タブレット、シーケンサー)

    現在、WindowsXP + VB6 + MSComm <ー> FXn2-16MR(RS232Cユニット)を シリアル通信で制御しています。これをWindows8.1(タブレット) + VB2013で全面的に 書き換えを行っています。テスト用のパソコンとは何の問題間無く通信は通りますが、 対シーケンサーだと送信はしているようだが、受信が全くできない状態です。 制御パラメータは、SerialPort1.Handshake=None, DtrEnable=True, RtsEnable=True 送信時のプロトコルは、<ENQ> + データ(ASCコード) 受信時のプロトコルは、<STX> + データ(ASCコード)+ <ETX> VB6は、この設定で動作しています。 VB2013では、制御パラメータは同じし送受信では普通に SerialPort1.Write、SerialPort1.ReadLineを使っています。 宜しくお願いします。

  • 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#とマイコンでSCI通信

    マイコンとC#で仮想COMポートを使ってSCI通信しているんですが、 ・「マイコン⇒C#」でデータを受信するときは、  正常に受信でき、 「C#⇒マイコン」がデータを受信するときは    正常に受信できません。 ・C#から何を送っても0x0aの値しかマイコンが受け取りません。 (TeraTermからは正常な値を受け取っています) 以上の点から、C#の送信プログラムの中身が悪いと思うのですが、 C#は初めて手をつけたのでよくわかりません。 送信にはWriteLine()関数を使っています serialPort1.WriteLine("a"); このような感じで一文字一文字送り、マイコンでLCDに表示させ結果を見ています。 シリアルポートの設定は次のように行っています try { beginTime = DateTime.Now; //←プログラムの関係上いれてるだけです this.serialPort1.PortName = this.textBox2.Text; this.serialPort1.BaudRate = 9600; this.serialPort1.Parity = System.IO.Ports.Parity.None; this.serialPort1.DataBits = 8; this.serialPort1.StopBits = System.IO.Ports.StopBits.One; serialPort1.Open(); serialPort1.DtrEnable = true; serialPort1.RtsEnable = true; } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } COMポートに関してはFormに別途ボタンを作りそこから選択するようにしています。 どこが悪いのか概要だけでも教えてほしいください;; よろしくおねがいしますm(__)m

  • 'Button1を押したらポートオープン

    'Button1を押したらポートオープン Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'シリアルポートを設定。 SerialPort1.PortName = SerialPortComboBox.Text SerialPort1.BaudRate = SerialBpsComboBox.Text Select Case SerialParityComboBox.Text Form3.SerialPort1.Parity = IO.Ports.Parity.None 'データ長 SerialPort1.DataBits = SerialDataBitsComboBox.Text 'RTSラインを有効にする SerialPort1.RtsEnable = True '送信タイムアウト SerialPort1.WriteTimeout = 3000 Try 'ポートをオープン SerialPort1.Open() 'いざ送信 'SerialPort1.Write(Chr(&HC)) 'ケーブルが外れた場合などのタイムアウトエラーなら、 Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Critical, "シリアル通信エラー") SerialPort1.Close() Exit Sub End Try '送信バッファが空になるまで待って、 While SerialPort1.BytesToWrite > 0 My.Application.DoEvents() End While ''''''''''''文字送信 'シリアルポート送信データをSJISに指定 SerialPort1.Encoding = System.Text.Encoding.GetEncoding(932) Dim Settei As String '送信文字代入 Settei = "A.1=" & vbCrLf 'いざ送信 SerialPort1.Write(Settei) '送信バッファが空になるまで待って、 While SerialPort1.BytesToWrite > 0 My.Application.DoEvents() End While End Sub '文字受信 Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Dim strDataReceived As String Dim add As New AddDataDelegate(AddressOf AddData) Try strDataReceived = SerialPort1.ReadLine Catch ex As Exception strDataReceived = ex.Message End Try TextBox1.Invoke(add, strDataReceived) End Sub ///////// 文字を送信した後に相手から帰ってきます。 送信した後の受信の部分ですが、これで正しいか教えて頂きたいです。

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

  • 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 ------------------------------------------------------------------------

  • VB2008でのシリアル通信

    VB2008のシリアル通信を使用して、ボタンを押した時にある機器に文字列(ここでは例として\"XXXX\")を送信しようとしているのですが、下記コードでは動作できません。 何がいけないのでしょうか? ボタンクリックのコードは省略 Using com1 As IO.Ports.SerialPort = _ My.Computer.Ports.OpenSerialPort("COM1") com1.WriteLine("XXXX" & vbCrLf) End Using アドバイスや参考URLなどありましたら教えてください。

  • 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 でどのように書けばよいのかわかりません。 どなたかご教授ください。 よろしくお願いいたします。

  • (VC++)シリアル通信について

    OS:Windows7 開発環境:VisualStudio2010 言語:C++ 機器:カードリーダ 接続:RS-232C VisualStudio2010にて、シリアル通信を行うプログラムを作成しています。 VisualStudioのヘルプや、いくつかのWebページを参考に、送信を行うところまではできています。 しかし、受信ができているのか、もしくは受信した内容が表示できていないのか分かりませんが、受信が確認できません。 送信はカードリーダが動くので分かりやすいのですが、受信は表示できないと確認できないためこのような状態です。 カードリーダの仕様は、あるASCIIコードを送るとカードが送られ、エラーステイタスコードが返ってきます。正常にカードが送られた場合は、またASCIIコードを送ると、読み取ったカードの情報がでてきます。(シリアル通信をテストするプログラムでは送信受信共に成功しています。) (送信)は、こちらが送ったもので、それ以外は受信した結果です。 ---------------以下その時の結果--------------- 3f 0d (送信) 30 10 45 30 31 32 30 30 38 0d (送信) 32 0d 33 59 0d 30 0d 31 59 0d 32 59 0d 33 0d 30 0d 31 0d ---------------------------------------------- C++のプログラムは以下の様になっています。 上記の結果でいうと、3f、0dを送り30を受け取るというところです。3f、0dでカードが送られ、30(正常終了)という結果を受け取ります。この結果をテキストボックスに表示したいと考えています。現在は、カードは送られるものの、30(もしくは他のエラーステイタスコード)という結果を表示することができません。 private: System::Void button_start_Click(System::Object^ sender, System::EventArgs^ e) {  serialPort1->Open();  serialPort1->Write(x3f); //defineにて定義(中身は?[0x3f])  serialPort1->Write(x0d); //defineにて定義(中身はCR[0x0d])  serialPort1->Close(); } delegate void SerialDataRecievedDelegate(String^ recvData); private: void SerialDataRecieved(String^ recvData) {  textBox1->Text = recvData; //確認するためにtextBox1に結果を表示 } private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {  SerialDataRecievedDelegate^ dlgte = gcnew SerialDataRecievedDelegate( this, &CardReader::Form1::SerialDataRecieved );  String^ RecievedData = serialPort1->ReadExisting();  //1バイトずつ受信  if(serialPort1->IsOpen == true) //シリアルポートが開いているか確認  {   COMRevieveBuffer = COMRevieveBuffer + RecievedData; //受信バッファに追加   if(RecievedData == "\r" ) //改行コード検出   {    RecievedData = RecievedData + "\n";    COMRevieveBuffer = COMRevieveBuffer + RecievedData;    //受信した一行をテキストボックスに転送    this->Invoke(dlgte, COMRevieveBuffer);    COMRevieveBuffer = "";   }   //エコーを返す   serialPort1->Write(RecievedData);  } } C言語でのプログラム作成はしていたのですが、VisualStudioやC++でのプログラム作成は初めてです。 ソースに変な点が多々あるとは思います。 ご教授お願いします。

専門家に質問してみよう