2016-03-01 125 views
0

我正在創建一個程序,使用串行端口使用某些設備。我有文檔詳細說明如何通過端口發送命令。它工作得很好,但我應該得到關於設備狀態的一些信息。我嘗試了一切,但我對這些類型的開發沒有信心。可能是我錯過了一些東西。SerialPort發送命令並獲得響應

從文檔:

總共有21級的命令,20個命令是開口的,1個命令是讀取狀態

打開命令:

地址命令固定值(0x55的)鎖號碼

地址0XF2 0X55 0X01

地址小號0XF2 0x55的0X02

地址0XF2 0x55的0X03

......

以上命令執行

成功返回: 地址+ 0×59 + 0×59

故障恢復:地址+ 0X5E + 0X5E

/// <summary> 
    /// Send open lokcer door command 
    /// </summary> 
    /// <param name="boardAddress">0 means open left slave cabinet,1 means open right slave cabinet</param> 
    /// <param name="command"></param> 
    /// <returns></returns> 
    public byte[] OpenBox(byte boardAddress, byte command) 
    { 
     var openCommand = new byte[5]; 
     openCommand[0] = (byte)(255 - boardAddress); 
     openCommand[0] = 0xF2; 
     openCommand[1] = 0x55; 
     openCommand[2] = command; 

     openCommand[3] = 0X00; 
     openCommand[4] = 0X00; 
     try 
     { 
      if (!serialPort.IsOpen) 
      { 
       //serialPort.WriteBufferSize = 5; 
       serialPort.Open(); 
      } 
      serialPort.DiscardInBuffer(); 
      serialPort.Write(openCommand, 0, 3); 
      return openCommand; 
     } 
     catch (ArgumentException ex) 
     { 
      throw new InvalidOperationException("Locker cell can not be opened.", ex); 
     } 
    } 

它工作得很好,但最後2個字節沒有返回。他們總是0X00。另外我使用SerialPortDataReceived,但我總是得到0。

public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     DBException.WriteLog(""); 
     DBException.WriteLog("Serial port data received"); 
     var sp = (SerialPort)sender; 
     DBException.WriteLog("Read existing = " + sp.ReadExisting()); 
     try 
     { 
      DBException.WriteLog("Length = " + sp.BytesToRead); 
      if (serialPort.BytesToRead == 4) 
      { 
       var readBuffer = new byte[4]; 
       sp.Read(readBuffer, 0, serialPort.BytesToRead); 

       DBException.WriteLog("Read serial port :" + readBuffer.ByteArrayToString()); 

       //     RaiseLockerStatusEvent(readBuffer.ByteArrayToString()); 
      } 
     } 
     catch (Exception ex) 
     { 
      DBException.WriteLog(ex); 
     } 
    } 

問題1如何獲得成功或失敗的回報?我認爲他們應該在最後2個字節。

問題2 如何獲取所有狀態?目前我什麼也沒有得到。

文檔:

讀鎖定狀態的命令:地址+數據1 +數據2 +數據3 地址:0XF10X55 數據1數據2數據3 0000 lock20 ... lock17 lock16 ... lock9 lock8 ...鎖1 的前4位是固定的數字0000 樣本: 0000 0000 0000 0001 0000 0001表示鎖定1,鎖定9打開,其他關閉 注意:對於某些類型的電子鎖定,「1」表示關閉,「0」表示打開。

我的片段

/// <summary> 
    /// Send check machine(cabinet) status command 
    /// </summary> 
    /// <param name="address">0 means check left cabinet, 1 means check right cabinet </param> 
    /// <returns></returns> 
    public byte[] SendCheckLockControlStatueCommand(byte address) 
    { 
     lock (this) 
     { 
      var checkCommand = new byte[6]; 
      checkCommand[0] = Convert.ToByte(255 - address); 
      checkCommand[1] = 0xF1; 
      checkCommand[2] = 0x55; 

      checkCommand[3] = 0x00; 
      checkCommand[4] = 0x00; 
      checkCommand[5] = 0x00; 
      try 
      { 
       if (!serialPort.IsOpen) 
       { 
        //     serialPort.WriteBufferSize = 5; 
        serialPort.Open(); 
       } 

       //Send inquiry command 
       serialPort.DiscardInBuffer(); 
       //     serialPort.DiscardOutBuffer(); 
       serialPort.Write(checkCommand, 0, 6); 

       return checkCommand; 
      } 
      catch (ArgumentException ex) 
      { 
       throw new InvalidOperationException("Locker cell can not be opened.", ex); 
      } 
     } 
    } 

回答

0

永遠不要使用異步DataReceived事件你的方式!您需要決定:要麼同步通信要麼要異步通信。如果你想要後者,絕不會打電話,甚至DataReceived等待

取而代之,將收到的東西放入緩衝區並在消息完成後立即處理。

此外,對ReadExisting的調用已經從串口讀取所有內容,因此Read很可能會被阻塞!

應該相當是這個樣子:

List<byte> receivedBinaryData = new List<byte>(); 

public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    var sp = (SerialPort)sender; 
    string availableData = sp.ReadExisting(); 
    byte[] inputAsASCII = Encoding.ASCII.GetBytes(availableData); 

    DBException.WriteLog(""); 
    DBException.WriteLog("Serial port data received"); 
    DBException.WriteLog("Read existing = " + availableData); 
    try 
    { 
     // Add the bytes to the receivedBinaryData List 
     receivedBinaryData.AddRange(inputAsASCII); 

     // If the message length is reached or exceeded, do something 
     if (receivedBinaryData.Length >= 4) 
      .... 
    } 
    catch (Exception ex) 
    { 
     DBException.WriteLog(ex); 
    } 
} 
+0

非常感謝你。我想我正在進入它。但實際上我更喜歡同步溝通。我想我應該在SendingCommand方法中等待一段時間,然後再讀取數據。你能解釋一下嗎?我會很感激。 –

+0

我想我已經找到了從串口讀取數據的正確答案。它會使用AutoResetEvent所有細節都在這裏。 http://stackoverflow.com/questions/11782053/serialport-wait-for-response再次感謝。 –

+0

如果你想同步交流,你可能想在Write之後調用Read,直到你有了答案。請注意,如果沒有答案,這可能會永遠阻止您的應用程序。超時使用WaitHandle確實是最好的解決方案。 –

相關問題