• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C# シリアル通信でデータ受信時の欠損について)

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

nak777rの回答

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.4

最初に _serialPort_DataReceived 関数で 5 Byte 読んで その後 _serialPort_DataReceived 関数で 40 Byte を読んだら、 途中からしか取れなかった。 関数の中には、「通信ポートを オープンしてるなら受信バッファをクリアする」 if (true == serialPort.IsOpen) { serialPort.DiscardInBuffer();//受信バッファをクリアする } という処理が入っているのですから当然そうなるのではないですか? 読込の関数を読んだ時点からデータの受信を開始するとした為、 それまで受信していたデータを捨ててまっさらな状態にする為 受信バッファをクリアしてるのですから そう考えれば解決方法は簡単で 受信バッファをクリアするの部分を受信バッファにある分、 全て別のバッファに読む様に修正して その別のバッファの中身を捨てるか、この後の本来の受信処理と つなげて処理するかを、通信フロー等を考慮しながら決めて 通信プログラムを作成します

fenri
質問者

お礼

>読込の関数を読んだ時点からデータの受信を開始するとした為、 それまで受信していたデータを捨ててまっさらな状態にする為 受信バッファをクリアしてるのですから なるほど。確かにそうですね。 なにが起こっているのかわからなかったのですがやっと理解出来ました。 ありがとうございます

関連するQ&A

  • visual c# 2010 シリアル通信アプリ

    http://www.kana-soft.com/tech/sample_0007.htm のサイトを参考に、マイコンとのシリアル通信評価に使うPCのアプリケーションを visual c# 2010で作っています。 一応データを受け取るようになったのですが、 63H 62H 61H 00H (アスキーコードだと"cba<null>") というデータを送っているはずなのですが、 扣a というデータが受信されてしまいます。 正しく受信するにはどうすれば良いでしょうか。 (該当していそうな部分のソースです) : : /****************************************************************************/ /*! * @brief データ受信が発生したときのイベント処理. * * @param [in] sender イベントの送信元のオブジェクト. * @param [in] e イベント情報. * * @retval なし. */ private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { //! シリアルポートをオープンしていない場合、処理を行わない. if (serialPort1.IsOpen == false) { return; } try { //! 受信データを読み込む. string data = serialPort1.ReadExisting(); //! 受信したデータをテキストボックスに書き込む. Invoke(new Delegate_RcvDataToTextBox(RcvDataToTextBox), new Object[] { data }); } catch (Exception ex) { MessageBox.Show(ex.Message); } } /****************************************************************************/ /*! * @brief 受信データをテキストボックスに書き込む. * * @param [in] data 受信した文字列. * * @retval なし. */ private void RcvDataToTextBox(string data) { //! 受信データをテキストボックスの最後に追記する. if (data != null) { rcvTextBox.AppendText(data); } }

  • シリアル受信データをファイルに書き出したい

    マイコンとPCをCOMポートで通信し、受信データをファイルに書き出したいのです。 やってみたこと1.と2.の間を埋める技術についてアドバイスをお願いします。 1.キーボード入力したテキストボックスの内容をファイルに書き出す ⇒書けました、OK     Dim xxx As New System.IO.StreamWriter("e:xxx.txt", False, System.Text.Encoding.Default) xxx.WriteLine(TextBox1.Text) xxx.Close() 2.サンプルコードでシリアル通信 ⇒受信データがテキストボックスに表示されました、OK     以下サイトを参考に勉強中、テキストボックス部分を抜粋させて頂きます     (http://www.kana-soft.com/tech/sample_0008_4.htm#1) 3.2.で表示されたテキストボックスの内容を、1.のように書き出したいのですが   上手くいきません。'■から'■間に xxx.WriteLine(RcvTextBox.Text) 書いてみましたが   e:xxx.txtは作成されません。delegate、invokeの理解不足が原因かと思うのですが、   調べ回るうちに・・・限界みたいです。(^_^;) (抜粋) '===== Private Delegate Sub Delegate_RcvDataToTextBox( data As String ) '===== Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Try '受信データを読み込む. Dim data As String data = SerialPort1.ReadExisting() '受信したデータをテキストボックスに書き込む. Dim args(0) As Object args(0) = data Invoke(New Delegate_RcvDataToTextBox(AddressOf Me.RcvDataToTextBox), args) Catch ex As Exception MsgBox( ex.Message ) End Try End Sub '===== Private Sub RcvDataToTextBox( data As String ) '受信データをテキストボックスの最後に追記する. If IsNothing( data ) = False Then RcvTextBox.AppendText( data ) End If '■     Dim xxx As New System.IO.StreamWriter("e:xxx.txt", False, System.Text.Encoding.Default) xxx.WriteLine(RcvTextBox.Text) xxx.Close()     '■ End Sub ===== 以上、駄目出しをよろしくお願いします。

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

  • 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方向に進むのですが、何故こんなことが起こるのでしょうか? 宜しくお願いします。

  • VS.NET2005 C#にてSerialPort受信されたときのイベントについて質問

    Visual Studio.NET2005ProにてSerialPort接続アプリケーションを開発しております。 受信が来たときのイベント DataReceived のところで、受信された文字列をテキストボックスへ表示させるということを行いたいのですが、エラーが出てしまいます。 ちなみにプログラムはこうです。 private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { //シリアルポートからデータを受信するたびに発生する textBox_all_in.Text = (string)serialPort.ReadByte(); } それで、エラーは エラー 1 型 'int' を型 'string' に変換できません。 このように出てしまいました。プログラミング初心者で、つまずいてしまいどうすればよいのかわからなく困っております。アドバイスよろしくお願いします。

  • シリアル通信で受信したデータによる図の描写

    RS-232Cのシリアル通信により受信したデータをもとに appletに図を描写するプログラムを考えています。 まず受信したデータをコマンドプロンプトに出力することはできたのですがプログラムを改良して 受信データを用いてappletに図を描こうとしたところ コンパイルはできたのですがappletで実行すると コマンドプロンプトにエラーメッセージが表示され実行できませんでした。 プログラムは以下の通りです。 分かる方がおられたらご回答のほどよろしくお願いします。 import javax.comm.*; import java.io.*; import java.util.*; import java.applet.Applet; import java.awt.*; public class SerialPortReader extends Applet implements SerialPortEventListener { protected SerialPort port; private InputStream is; public int newData; public void init(){ String portName = "COM6"; CommPortIdentifier portID = null; try{ // COM6 のCommPortIdentifier を取得 portID = CommPortIdentifier.getPortIdentifier(portName); }catch(NoSuchPortException ex){ ex.printStackTrace(); System.exit(1); } try{ //ポートのオープン port = (SerialPort)portID.open("SerialPortWriter", 5000); }catch(PortInUseException ex){ ex.printStackTrace(); System.exit(1); } try { // 通信速度などの通信条件の設定 port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT); } catch (UnsupportedCommOperationException ex){ ex.printStackTrace(); System.exit(1); } try { // SerialPortEvent を受け取るためのリスナの登録 port.addEventListener(this); } catch(TooManyListenersException ex){ ex.printStackTrace(); System.exit(1); } // Data Available イベントを受け取るようにする port.notifyOnDataAvailable(true); try { //COM6ポートから入力ストリームを取得する is = port.getInputStream(); } catch (IOException ex){ ex.printStackTrace(); System.exit(1); } } //受信データの大きさの円を描く public void paint(Graphics g) { g.fillOval(50, 50 , newData , newData); } // SerialPortEvent 処理ルーチン public void serialEvent(SerialPortEvent event) { newData = 0; switch(event.getEventType()) { case SerialPortEvent.BI: case SerialPortEvent.OE: case SerialPortEvent.FE: case SerialPortEvent.PE: case SerialPortEvent.CD: case SerialPortEvent.CTS: case SerialPortEvent.DSR: case SerialPortEvent.RI: case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // Data Available 以外のイベントは処理しない break; case SerialPortEvent.DATA_AVAILABLE: while (newData != -1) { try { //入力ストリームから次のバイトデータを読み込む newData = is.read(); //十進数のアスキーコードから0~9の整数に変換 newData = newData - 48; //受信データを元にグラフ表示 repaint(); //入力ストリームからバイトデータがなくなったら処理を終える if (newData == -1) { break; } } catch (IOException ex) { System.err.println(ex); return; } } break; } } }

    • ベストアンサー
    • Java
  • 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

  • C#にてCTI。RS232Cの受信と送信について。

    C#でCTI機能の実現を目指しております。 プログラムは以下サイトからDLして改造しています。 http://tmp.junkbox.info/e14.html しかし、エラーが頻発し原因不明です。 構成、仕様としては、 アロハPC1という機械から電話番号データを受信しPCに受け渡し。 ・データを受け取る(ここは問題なし) データ形式は STX(02H)、着信日時(月日曜時分9桁)、電話番号(20桁)、ETX(03H) として送られてきます。 例) 1214112050457771111 ・正常データの場合はACK(06H)を返信(これをしない場合1秒後に同データが再送される) ・データ整形 ・データ表示 というような形にしたいのです。 上記サイトのプログラムをアロハPC1に合わせて通信できるようにした状態ですと、例のような生データが問題なく表示されます。 これを以下のようにしてみましたが、エラーが出てしまいます。 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { // 受信文字列の取得 string receivedData = ""; string moji = ""; string moji2 = ""; try { receivedData = this.serialPort1.ReadExisting(); receivedData = receivedData.Replace(this.serialPort1.NewLine, "\r\n"); string[] week = { "(日)", "(月)", "(火)", "(水)", "(木)", "(金)", "(土)" }; string stx = receivedData.Substring(0, 1); string etx = receivedData.Substring(30, 1); // ACKを返す。 byte[] ack_data = new byte[1]; ack_data[0] = 06; serialPort1.Write(ack_data,0,1); string data_m = receivedData.Substring(1, 2); string data_d = receivedData.Substring(3, 2); string w = receivedData.Substring(5, 1); int w2 = int.Parse(w); string data_w = week[w2]; string data_h = receivedData.Substring(6, 2); string data_i = receivedData.Substring(8, 2); moji2 = receivedData.Substring(10, 20); // スペースを痴漢 moji2 = moji2.Replace(" ", ""); moji = data_m + "月" + data_d + "日" + data_w + data_h + "時" + data_i + "分 "; if (moji2 == "P") { moji = moji + "着信番号非通知\n"; } else if (moji2 == "O") { moji = moji + "着信番号提供地域外\n"; } else if (moji2 == "C") { moji = moji + "公衆電話\n"; } else { moji = moji + moji2 + "\n"; } } catch (Exception ex) { moji = ex.Message; } // richTextBox側のスレッドに AddRecievedDataメソッドのポインタを渡して、 // 受信文字列を追加させる AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData); this.richTextBox1.Invoke(add, moji); } 結果: 1221112260457771111 12月21日(月)12時26分 0457771111 1221112 startIndex に文字列の長さより大きい値を指定することはできません。 パラメータ名: startIndex260457771111 startIndex に文字列の長さより大きい値を指定することはできません。 パラメータ名: startIndex Substringを削除すると「startIndex に文字列の長さより大きい値を指定することはできません。」というようなエラーは出てきません。 receivedData = this.serialPort1.ReadExisting(); を文字列を直接代入した場合はエラーは発生しません。 これをどのようにすれば正常に動くのでしょうか。 また、ACKが正常に送信できてないみたいなのも解れば助かります。 よろしくお願いします。

  • VB2010 シリアル受信した情報を表示する

    VB2010 シリアル受信した情報を表示する フォームが表示されたらポートを開けてテキストボックスに文字を表示させたいです。 送られてくる情報はSTXとETXで挟まれた数十文字のアスキー文字です。 フォーム表示中は、teratermやハイパーターミナルで接続不可エラーが出ますし その逆でteratermやハイパーターミナルで接続している時にはcomポートエラーが出ます。 teratermやハイパーターミナルではシリアルで受信した文字が表示されています。 そのような状況で下記、シンプルなコードを作りましたが表示されません。 テキストボックスが何も変化しない状態です。なんでもいいので、テキストボックスに受信した情報を出してみたいです。 http://msdn.microsoft.com/ja-jp/library/cc720852.aspx を参考に受信部分に使っています。 Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call SerialPort1.Open() End Sub Delegate Sub AddDataDelegate(ByVal str As String) Private Sub AddData(ByVal str As String) TextBox1.Text = TextBox1.Text + str 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 End Class

  • (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++でのプログラム作成は初めてです。 ソースに変な点が多々あるとは思います。 ご教授お願いします。