2017-08-24 36 views
0

經過很長時間我需要再次編程。 我需要不斷地通過串口從汽車ecu(?data)發送一個命令。c#不斷請求和處理來自串口的數據

然後我需要接收那些我將要在顯示器上顯示的數據(思考賽車顯示器和汽車參數如溫度等)。 我需要不斷地做到這一點

我不知道在我開始之前什麼是最好的方式來做到這一點?

1個用於不斷詢問和接收數據的線程 用於在屏幕上顯示數據的主線程。 (將數據存入緩衝區並保存一分鐘左右)

任何人有任何提示或指導如何開始。 我測試了接收數據與終端,我得到了數據,所以配置工作。

發送?數據=>我拿回數據。

回答

0

的方法,我們正在使用我們的SerialPort處理程序是,以有一個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(); 
    } 
} 

一個串口被初始化並打開。之後,我們連接所有需要的事件,並致電SendDataCommand()方法。該方法是從某個任務調用的公共可見方法。這稱爲方法SendData。只要有答案,就會觸發事件並開始解釋。如果在指定的時間內完成解釋(_autoResetEvent.WaitOne(msToWait)),則結果返回給調用方法。 這應該在一個單獨的任務中完成,所以當你等待答案時,UI將不會阻止。

如上所述,這是一個非常簡明的例子。您應該在收到的SerialPort處理程序中執行更多檢查,因爲該事件存在一些問題。通過這種方法,您將對業務邏輯有更多的抽象。

希望這會有所幫助。

+0

感謝您的信息 – Ditn

1

你可以只使用SerialPort類和配置波特率,數據位等..然後就等着DataReceived事件檢索到火:

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... 
}