2010-11-20 12 views
2

シリアルでバイトを送受信したいと思います。私の受信者は、バイトを非同期的に取得する必要があります。下にある小さな例を書いたが、それはうまくいくと思われるが、それは不安を感じさせる。SerialPortクラスとDataReceivedイベント...バイトの取得。 ReadLineまたはReadExistingを使用しますか?どんな例?

  1. 私は実際にWriteLine、ReadLineを使用する必要がありますか?今書いているように、イベントハンドラm_port_DataReceivedのコードは、各バイトごとに呼び出される可能性がありますか?それはイベント "DataReceived"の私の理解でした。おそらく私は間違っています。 ReadLineは、行末の文字が見えるまでブロックしますか?

  2. 「if(e.EventType == SerialData.Eof)」をイベントハンドラで使用する必要がありますか?私はそれがコメントアウトされているのを見ることができます。私はそれを試して、それを働かせることができませんでした。いつSerialData.Eofを期待しますか?私の考えは、 "ReadExisting"を呼び出す前にすべてのバイトが存在する前に待つことができたということでした。しかし、 "if"文は真と評価されませんでした。コードをReadExistingに移動させると、すべてのバイトを正しく読み取ることができました。

  3. 一般的に、シリアルポート経由のバイトを受信するようにコードを設定するにはどうすればよいですか?送信者は125ミリ秒ごとに小さなチャンクを送信しますが、特殊文字は送信しません。バイトのパケットは時間的に離れているので、パケットを混在させるという問題はないと思います。より多くの問題は、「一度バイトを見ると、すべてのものを読んでください。非常に短い時間を待っている限り、すべてを得ます」。このシナリオを考えると、好ましい方法がありますか?事前に

おかげで、この簡単な使用例を示しMSDNで デイブ

public class SerialPortController 
{ 
    SerialPort m_port; 

    public SerialPortController(bool server) 
    { 


     if (server) 
     { 
      m_port = new SerialPort("COM4"); 
      m_port.BaudRate = 115200; 
      m_port.Open(); 
      byte[] sillyBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; 
      ASCIIEncoding encoding = new ASCIIEncoding(); 
      string output_string = encoding.GetString(sillyBytes); 
      m_port.WriteLine(output_string); 
      //m_port.Write(sillyBytes, 0, 8);     
     } 
     else 
     { 
      m_port = new SerialPort("COM5"); 
     m_port.DataReceived += new SerialDataReceivedEventHandler(m_port_DataReceived); 
      m_port.BaudRate = 115200; 
      m_port.Open(); 
     } 
     int character = Console.Read(); 
    } 

    void m_port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     //if (e.EventType == SerialData.Eof) 
     { 
      // string answer = m_port.ReadExisting(); 
      string answer = m_port.ReadLine(); 
      ASCIIEncoding encoding = new ASCIIEncoding(); 
      byte[] byte_answer = encoding.GetBytes(answer); 

     } 
    } 
} 
+0

少なくとも1受信するバイトであるときに、プロパティReceivedBytesThreshold = 1は、(デフォルトであり、あなたがそれを変更したことを表示されません)、そしてDataReceivedEventが発火すると仮定。もっとあるかもしれない。これは*受信されたバイトごとに発生するイベントと同じではありません。これは、発火したときに少なくとも1バイトが存在することを意味します。 – Andy

+0

私が常に問題なく使用してきたアプローチは、DataRcvdハンドラが起動するときにデータをバイト配列として読み込むことです。そのバイト配列のバッファをキューに入れます。私がデータを必要とするときに、一緒に戻して使用/変換する...アプリケーションに応じて、私は次のうちの1つを行います:1 - DataRcvdハンドラはUIスレッド上でイベントを発生させます。 2 - タイマーを使用する。 3 - DataRcvdハンドラはUIスレッド上のメソッドを呼び出します。 – dbasnett

答えて

2

There'sと例。

ReadLineの代わりにReadExistingを使用しました。ドキュメントからも

は:

DataReceivedイベントは、受け取った各バイトに対して発生することが保証されていません。 BytesToReadプロパティを使用して、バッファに読み込まれるデータの量を判断します。

private static void DataReceviedHandler(
        object sender, 
        SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    string indata = sp.ReadExisting(); 
    Console.WriteLine("Data Received:"); 
    Console.Write(indata); 
} 
+0

ありがとう、それはそれをクリア! – Dave

+0

私はこれをしましたが、ハンドラはうまく反応しません。受信するデータごとに、受信した10データのうち約1データのみを認識します。なぜなのかご存知ですか? –

+0

@ConradCわかりませんが、あなたのイベントは1/10回トリガされたと言っていますが、ReadExistingを読んでいるとデータが失われていますか?あなたはバッファが小さすぎるかもしれませんか? http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readbuffersize(v=vs.110).aspx –

関連する問題