Modbus通讯协议

什么是 Modbus

Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。Modbus 协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。

Modbus 是一个请求/应答协议

Modbus

以下是要分解的Modbus热图

 

Modbus消息帧

 

了解了它,会使你对串口通信有一个清晰的认识!

通用消息帧

 

ASCII消息帧 (在消息中的每个8Bit 字节都作为两个ASCII字符发送)

十六进制,ASCII字符0...9,A...F

消息中的每个ASCII字符都是一个十六进制字符组成

每个字节的位

1个起始位

n个数据位,最小的有效位先发送

1个奇偶校验位,无校验则无

1个停止位(有校验时),2个Bit(无校验时)

错误检测域

LRC(纵向冗长检测)

RTU消息帧

8位二进制,十六进制数0...9,A...F

消息中的每个8位域都是一个两个十六进制字符组成

每个字节的位

1个起始位

8个数据位,最小的有效位先发送

1个奇偶校验位,无校验则无

1个停止位(有校验时),2个Bit(无校验时)

错误检测域

CRC(循环冗长检测)

 

public static string CRCCheck(string val)

        {

            string hexString = string.Empty;

             val = val.TrimEnd('');

            string[] spva = val.Split('');

            byte[] bufData = newbyte[spva.Length + 2];

            bufData = ToBytesCRC(val);

            ushort CRC = 0xffff;

            ushort POLYNOMIAL = 0xa001;

            for (int i = 0; i < bufData.Length - 2; i++)

            {

                CRC ^= bufData[i];

                for (int j = 0; j < 8; j++)

                {

                    if ((CRC & 0x0001) != 0)

                    {

                        CRC >>= 1;

                        CRC ^= POLYNOMIAL;

                    }

                    else

                    {

                        CRC >>= 1;

                    }

                }

            }

            byte[] bytes = System.BitConverter.GetBytes(CRC));

           

            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();

                for (int i = 0; i < bytes.Length; i++)
                {
                    strB.Append(bytes[i].ToString("X2"));
                }
                hexString = strB.ToString();
            }
            return hexString;

        }

        ///<summary>

        ///例如把如下字符串转换成字节数组

        /// AA AA AA AA 0A 00 68 00 06 03 04 54 21 28 22 E5 F3 16 BB BB BB BB   转换为字节数组

        ///</summary>

        ///<param name="hex">十六进制字符串</param>

        ///<returns></returns>

        publicstaticbyte[] ToBytesCRC(string hex)

        {

            string[] temp = hex.Split('');

            byte[] b = newbyte[temp.Length + 2];

 

            for (int i = 0; i < temp.Length; i++)

            {

                b[i] = Convert.ToByte(temp[i], 16);

            }

 

            return b;

        }

        ///<summary>

        ///将字节数据转换为十六进制字符串,中间用 “ ”分割如:AA AA AA AA 0A 00 68 00 06 03 04 54 21 28 22 E5 F3 16 BB BB BB BB

        ///</summary>

        ///<param name="vars">要转换的字节数组</param>

        ///<returns></returns>

        publicstatic String ToHex(byte[] vars)

        {

            return BitConverter.ToString(vars).Replace('-''').Trim();

        }

CS校验(累加和)

publicstaticstring CSCheck(string str)

        {

            if (str.Length == 0return"";

            else str = str.Trim();

            byte[] sss = ToBytes(str);

            int n = 0;

            for (int i = 0; i < sss.Length; i++)

            {

                n += sss[i];

            }

            return ToHex(n);

        }

        ///<summary>

        /// AB CD 12 3B     转换为字节数组

        ///</summary>

        ///<param name="hex">十六进制字符串</param>

        ///<returns></returns>

        publicstaticbyte[] ToBytes(string hex)

        {

            string[] temp = hex.Split('');

            byte[] b = newbyte[temp.Length];

 

            for (int i = 0; i < temp.Length; i++)

            {

                if (temp[i].Length > 0)

                    b[i] = Convert.ToByte(temp[i], 16);

            }

 

            return b;

        }

        ///<summary>

        ///转换为符合本程序的十六进制格式

        ///</summary>

        ///<param name="var">1 2 3 等。</param>

        ///<returns>返回十六进制字符串,如果是1-9的话,前面带零</returns>

        ///<example>例如: 5  ="05"  12 ="0C" 无论何时,都是两位数。  </example>

        publicstaticstring ToHex(intvar)

        {

            int cs = var;

            string tmp = "";

            if (cs == 0) { tmp = "00"; }

            while (cs > 0)

            {

                int ys;

                cs = Math.DivRem(cs, 256out ys);

                tmp = tmp.Insert(0string.Format(" {0}", Right("00" + Convert.ToString(ys, 16), 2).ToUpper()));

            }

            return tmp.Trim();

        }

        publicstaticstring Right(string str, int Length)

        {

            if ((Length <= 0) || (str == null))

            {

                return"";

            }

            int length = str.Length;

            if (Length >= length)

            {

                return str;

            }

            return str.Substring(length - Length, Length);

        }

LRC校验(LRC错误校验用于ASCII模式)

///<summary>

        ///取模FF(255)

        ///取反+1

        ///</summary>

        ///<param name="writeUncheck"></param>

        ///<returns></returns>

        publicstaticstring LRCheck(string writeUncheck)

        {

            char[] hexArray = newchar[writeUncheck.Length];

            hexArray = writeUncheck.ToCharArray();

            int decNum = 0, decNumMSB = 0, decNumLSB = 0;

            int decByte, decByteTotal = 0;

 

            bool msb = true;

 

            for (int t = 0; t <= hexArray.GetUpperBound(0); t++)

            {

                if ((hexArray[t] >= 48) && (hexArray[t] <= 57))

 

                    decNum = (hexArray[t] - 48);

 

                elseif ((hexArray[t] >= 65) & (hexArray[t] <= 70))

                    decNum = 10 + (hexArray[t] - 65);

 

                if (msb)

                {

                    decNumMSB = decNum * 16;

                    msb = false;

                }

                else

                {

                    decNumLSB = decNum;

                    msb = true;

                }

                if (msb)

                {

                    decByte = decNumMSB + decNumLSB;

                    decByteTotal += decByte;

                }

            }

 

            decByteTotal = (255 - decByteTotal) + 1;

            decByteTotal = decByteTotal & 255;

 

            int a, b = 0;

 

            string hexByte = "", hexTotal = "";

            double i;

 

            for (i = 0; decByteTotal > 0; i++)

            {

                b = Convert.ToInt32(System.Math.Pow(16.0, i));

                a = decByteTotal % 16;

                decByteTotal /= 16;

                if (a <= 9)

                    hexByte = a.ToString();

                else

                {

                    switch (a)

                    {

                        case10:

                            hexByte = "A";

                            break;

                        case11:

                            hexByte = "B";

                            break;

                        case12:

                            hexByte = "C";

                            break;

                        case13:

                            hexByte = "D";

                            break;

                        case14:

                            hexByte = "E";

                            break;

                        case15:

                            hexByte = "F";

                            break;

                    }

                }

                hexTotal = String.Concat(hexByte, hexTotal);

            }

            return hexTotal;

        }

 

        publicvoid LRCheck(byte[] code)

        {

            int sum = 0;

            foreach (byte b in code)

            {

                sum += b;

            }

            sum = sum % 255;//取模FF(255)

            sum = ~sum + 1;//取反+1

            string lrc = Convert.ToString(sum, 16);

            return lrc;

        }

 

 

自定义Modbus数据表

 

自定义Modbus数据表例子:

设备相关读取信息:

命令报文信息解析:

自定义Modbus数据表定义注意

 

串口调试工具

 

串口调试工具的使用.

 

串口调试工具 + RS485  就可以读取硬件上的数据,和向硬件请求了,如何使用请看“调试篇”会有详细的说明。

 

网络调试助手:

       调试助手主要还是TCP协议通讯的一个调试工具

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值