【问题标题】:SerialPort to send command and to get responseSerialPort 发送命令并获得响应
【发布时间】:2016-03-01 14:17:12
【问题描述】:

我正在创建一个程序来使用串行端口与某些设备一起工作。我有文档,其中详细说明了如何通过端口发送命令。它工作得很好,但我应该得到一些关于设备状态的信息。我尝试了一切,但我对这种类型的开发没有信心。可能是我错过了什么。

来自文档:

共有21条指令,20条开启指令,1条读取状态指令

打开命令:

地址命令固定值(0x55)锁号

地址0XF2 0X55 0X01

地址0XF2 0X55 0X02

地址0XF2 0X55 0X03

......

以上命令执行

成功返回: 地址+0X59+0X59

失败返回​​:地址+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如何获得Success or Failure返回?我认为它们应该在最后 2 个字节中。

问题 2 如何获得所有状态?我目前一无所获。

文档:

读锁状态指令:地址+Data1+Data2+Data3 地址:0XF10X55 数据1 数据2 数据3 0000 lock20 … lock17 lock16 … lock9 lock8 … lock1 前 4 位是固定数字 0000 样本: 0000 0000 0000 0001 0000 0001 表示lock1和lock9打开,其他关闭 注意:对于某些类型的电子锁,“1”表示关闭,“0”表示打开。

我的sn-p

/// <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);
            }
        }
    }

【问题讨论】:

    标签: c# serial-port


    【解决方案1】:

    永远不要像你那样使用异步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);
        }
    }
    

    【讨论】:

    • 非常感谢。我想我正在进入它。但实际上我更喜欢同步通信。而且我认为我应该在我的 SendingCommand 方法中等待一段时间,然后读取数据。你能解释一下吗?我会很感激的。
    • 我想我找到了从串口读取数据的正确答案。它将使用 AutoResetEvent 所有详细信息都在这里。 stackoverflow.com/questions/11782053/… 再次感谢。
    • 如果你想同步通信,你可能想在你Write之后调用Read直到你得到答案。请注意,如果没有答案,这可能会永远阻止您的申请。使用带有超时的 WaitHandle 确实可能是最好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 2015-12-05
    相关资源
    最近更新 更多