Modbus 功能 0x06

Modbus function 0x06

遇到问题。有一个0x03的功能,但是我需要在0x06重做,我不明白怎么做。

我知道函数 06 没有可变部分。一个寄存器的值总是传送给它。但是我不明白需要纠正什么。请帮忙

这里我为函数创建了一个包:

 private void BuildMessage(byte address, byte type, ushort start, ushort registers, ref byte[] message)
                {
                    if (type == 3 || type == 16)
                    {
                        //Array to receive CRC bytes:
                        byte[] CRC = new byte[2];

                        message[0] = address;
                        message[1] = type;
                        message[2] = (byte)(start >> 8);
                        message[3] = (byte)start;
                        message[4] = (byte)(registers >> 8);
                        message[5] = (byte)registers;

                        GetCRC(message, ref CRC);
                        message[message.Length - 2] = CRC[0];
                        message[message.Length - 1] = CRC[1];
                    }
                    else if (type == 6)
                    {
                        byte[] CRC = new byte[2];

                        message[0] = address;
                        message[1] = type;
                        message[2] = (byte)(start >> 8);
                        message[3] = (byte)start;
                        message[4] = (byte)(registers >> 8);
                        message[5] = (byte)registers;

                        GetCRC(message, ref CRC);
                        message[6] = CRC[0];
                        message[7] = CRC[1];
                    }
        }

这是我的功能编号 3:

 public bool SendFunc(int funcNumer, string connectType, byte address, ushort start, ushort registers, ref short[] values)
            {
                #region №3
                if (funcNumer == 3)
                {
                    #region serial-port
                    if (connectType.Equals("COM"))
                    {
                        //Ensure port is open:
                        if (sp.IsOpen)
                        {
                            //Clear in/out buffers:
                            sp.DiscardOutBuffer();
                            sp.DiscardInBuffer();
                            //Function 3 request is always 8 bytes:
                            byte[] message = new byte[8];
                            //Function 3 response buffer:
                            byte[] response = new byte[5 + 2 * registers];
                            //Build outgoing modbus message:
                            BuildMessage(address, (byte)3, start, registers, ref message);
                            //Send modbus message to Serial Port:
                            try
                            {
                                sp.Write(message, 0, message.Length);
                                GetResponse("COM", ref response);
                            }
                            catch (Exception err)
                            {
                                modbusStatus = "" + err.Message;
                                return false;
                            }
                            //Evaluate message:
                            if (CheckResponse(response))
                            {
                                //Return requested register values:
                                for (int i = 0; i < (response.Length - 5) / 2; i++)
                                {
                                    values[i] = response[2 * i + 3];
                                    values[i] <<= 8;
                                    values[i] += response[2 * i + 4];
                                }
                                modbusStatus = "";
                                return true;
                            }
                            else
                            {
                                modbusStatus = "";
                                return false;
                            }
                        }
                        else
                        {
                            modbusStatus = "";
                            return false;
                        }
                    }

我在这里尝试实现功能编号 6:

if (funcNumer == 6)
            {
                #region serial-port
                if (connectType.Equals("COM"))
                {
                    //Ensure port is open:
                    if (sp.IsOpen)
                    {
                        //Clear in/out buffers:
                        sp.DiscardOutBuffer();
                        sp.DiscardInBuffer();
                        //Function 3 request is always 8 bytes:
                        byte[] message = new byte[8];
                        //Function 3 response buffer:
                        byte[] response = new byte[5 + 2 * registers];
                        //Build outgoing modbus message:
                        BuildMessage(address, (byte)6, start, registers, ref message);
                        //Send modbus message to Serial Port:
                        try
                        {
                            sp.Write(message, 0, message.Length);
                            GetResponse("COM", ref response);
                        }
                        catch (Exception err)
                        {
                            modbusStatus = "" + err.Message;
                            return false;
                        }
                        //Evaluate message:
                        if (CheckResponse(response))
                        {
                            //Return requested register values:
                            for (int i = 0; i < (response.Length - 5) / 2; i++)
                            {
                                values[i] = response[2 * i + 3];
                                values[i] <<= 8;
                                values[i] += response[2 * i + 4];
                            }
                            modbusStatus = "";
                            return true;
                        }
                        else
                        {
                            modbusStatus = "";
                            return false;
                        }
                    }
                    else
                    {
                        modbusStatus = "";
                        return false;
                    }
                }

这是我检查响应的函数:

 private bool CheckResponse(byte[] response)
        {
            //Perform a basic CRC check:
            byte[] CRC = new byte[2];
            GetCRC(response, ref CRC);
            if (CRC[0] == response[response.Length - 2] && CRC[1] == response[response.Length - 1])
                return true;
            else
                return false;
        }

这是我获取响应的函数:

private void GetResponse(string connect, ref byte[] response)
        {
            if (connect.Equals("COM"))
            {
                for (int i = 0; i < response.Length; i++)
                {
                    response[i] = (byte)(sp.ReadByte());
                }
            }
            else if (connect.Equals("TCP"))
            {
                NetworkStream stream = tcpClient.GetStream();

                for (int i = 0; i < response.Length; i++)
                {
                    response[i] = (byte)(stream.ReadByte());
                }
            }
            else
            {

            }            
        }

Modbus 函数 0x03 and 0x06 之间的区别实际上是您在问题中没有显示的代码部分:CheckResponse(response).

函数 0x03 读取多个寄存器,这些寄存器中的值(来自从属)包含在响应中。

函数 0x06 写入一个 单个 寄存器并返回回显。所以响应与查询相同。

有了这些信息,修改代码应该很容易:删除检索寄存器值的 for 循环。

除此之外,您可能还需要修改 CheckResponse() 函数,但这也应该非常简单:只需检查响应是否与查询(消息)完全相同。

编辑: 如果您的 CheckResponse()` 函数只检查响应的正确 CRC,我想您可以保持原样。