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(循环冗长检测)

CRC校验 (http://baike.baidu.com/view/1664507.htm)

public static string CRCCheck(string val)        {            val = val.TrimEnd(' ');            string[] spva = val.Split(' ');            byte[] bufData = new byte[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;                    }                }            }            return Maticsoft.DBUtility.HLConvert.ToHex(System.BitConverter.GetBytes(CRC));        }        /// <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>        public static byte[] ToBytesCRC(string hex)        {            string[] temp = hex.Split(' ');            byte[] b = new byte[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>        public static String ToHex(byte[] vars)        {            return BitConverter.ToString(vars).Replace('-', ' ').Trim();        }

CS校验(累加和)

public static string CSCheck(string str)        {            if (str.Length == 0) return "";            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>        public static byte[] ToBytes(string hex)        {            string[] temp = hex.Split(' ');            byte[] b = new byte[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>        public static string ToHex(int var)        {            int cs = var;            string tmp = "";            if (cs == 0) { tmp = "00"; }            while (cs > 0)            {                int ys;                cs = Math.DivRem(cs, 256, out ys);                tmp = tmp.Insert(0, string.Format(" {0}", Right("00" + Convert.ToString(ys, 16), 2).ToUpper()));            }            return tmp.Trim();        }        public static string 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>        public static string LRCheck(string writeUncheck)        {            char[] hexArray = new char[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);                else if ((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)                    {                        case 10:                            hexByte = "A";                            break;                        case 11:                            hexByte = "B";                            break;                        case 12:                            hexByte = "C";                            break;                        case 13:                            hexByte = "D";                            break;                        case 14:                            hexByte = "E";                            break;                        case 15:                            hexByte = "F";                            break;                    }                }                hexTotal = String.Concat(hexByte, hexTotal);            }            return hexTotal;        }        public void 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;        }
(0)

相关推荐