2017-08-24 18 views
0

私はもう一度プログラムする必要があります。 私はcar ecu(?data)からシリアルポートを介してコマンドを絶えず送る必要があります。c#シリアルポートからデータを絶えずリクエストして処理しています

私はディスプレイ上に表示するために処理するデータを受け取る必要があります(温度などの車のパラメータを使ってレーシングディスプレイを考える)。 私は常にこれを行う必要があります

私はこれを行うには何が最善の方法を開始するのだろうか?

1つのスレッドが常にデータを要求して受信します。 画面にデータを表示するためのメインスレッド。 (バッファにデータを保存して1分程度で保存してください)

誰もが参考になるようなヒントがあります。 私は端末でデータを受信したことをテストしました。データが戻ってきてconfigが動作しています。

が送信されますか? data =>私はデータを取り戻しました。

答えて

0

アプローチをポートからの応答があるとすぐに通知を受けるにはAutoResetEventが必要です。

SerialPort FrameWorkのクラスには、統合されたDataReceivedイベントにいくつかの問題があります。利用可能な完全なパッケージがない場合(解答の長さを定義した場合)、時には解雇されることがあります。だからあなたはあなたが期待する答えの長さを調べるべきです。

私たちの非常にストリップダウン実装は:

public class Serialport 
{ 
    private SerialPort _serialPort; 
    private List<byte> _buffer; 
    private AutoResetEvent _autoResetEvent; 
    private const int WriteTimeOut = 5; 

    private event EventHandler ReceivedDataChanged; 

    public Serialport() 
    { 
     _serialPort = new SerialPort(); 

     // set PortName, BaudRate etc 

     _serialPort.Open(); 
     _serialPort.DiscardInBuffer(); 
     _serialPort.DiscardOutBuffer(); 
     _serialPort.DataReceived += ReceiveData; 
    } 

    private void ReceiveData(object sender, SerialDataReceivedEventArgs e) 
    { 
     var bytes = _serialPort.BytesToRead; 

     byte[] buffer = new byte[bytes]; 
     if (_serialPort.IsOpen) 
     { 
      _serialPort.BaseStream.Read(buffer, 0, bytes); 
      _buffer.AddRange(buffer); 
     } 

     ReceivedDataChanged?.Invoke(this, new ReceivedBytesEventArgs(_buffer.ToArray())); 
     _buffer.Clear(); 
    } 

    private void SendData(byte[] message, int answerLength) 
    { 
     _serialPort.ReceivedBytesThreshold = answerLength; 
     _serialPort.WriteTimeout = WriteTimeOut; 
     _serialPort.Write(message, 0, message.Length); 
    } 

    public string SendDataCommand() 
    { 
     if (_serialPort.IsOpen) 
     { 
      ReceivedDataChanged += InterpretAnswer; 
      SendData(message, length); 
      if (_autoResetEvent.WaitOne(100)) 
      { 
       ReceivedDataChanged -= InterpretAnswer; 
       //Data Received and interpreted and send to the caller 
       return _requestAnswer; 
      } 

      ReceivedDataChanged -= InterpretAnswer; 
     } 

     return "Connection not open"; 
    } 

    private void InterpretAnswer(object sender, EventArgs e) 
    { 
     // handle all interpretation 
     // Set the event 
     _autoResetEvent.Set(); 
    } 
} 

SERIALPORTは、初期化して開かれました。その後、必要なすべてのイベントを結び、SendDataCommand()メソッドに電話します。このメソッドは、一部のタスクから呼び出されるパブリックな可視メソッドです。これによりメソッドSendDataが呼び出されます。回答があるとすぐに、イベントがトリガーされ、解釈が開始されます。指定された時間内に解釈が行われた場合(_autoResetEvent.WaitOne(msToWait))、結果は呼び出し元のメソッドに返されます。 これは別のタスクで行う必要がありますので、応答を待つ間にUIはブロックされません

前述のように、これは非常に除外された例です。イベントにいくつかの問題があるので、SerialPortの受信ハンドラでさらにチェックを行う必要があります。このアプローチを使用すると、ビジネスロジックの抽象度がさらに向上します。

これが役に立ちます。

+0

ありがとうございます – Ditn

1

あなただけSERIALPORTクラスを使用することができそして、データビットなど。ボーレートを設定してからちょうど火にDataReceivedイベントを待つ:私たちは、ある私たちのSerialPortハンドラで使用している

public class SerialPortReader 
{ 
    public SerialPortReader(string yourPortName) 
    { 
     var serialPort = new SerialPort() { 
      PortName = yourPortName, 
      BaudRate = 57600; //This will control the rate at what you receive the data 
     } 

     serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived); 

     serialPort.Open(); 
    } 
} 

public void OnDataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    var serialPort = (SerialPort)sender; 
    // Process your data reading the stream with Read, ReadLine etc... 
} 
関連する問題