2016-03-01 102 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确实是最好的解决方案。 –

相关问题