Modbus协议 CRC 校验码

Posted GuGu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Modbus协议 CRC 校验码相关的知识,希望对你有一定的参考价值。

CRC(循环冗余校验)在线计算 http://www.ip33.com/crc.html

里面的8005的多项式值,但网上看到的算法都是用A001来异或的

-----------------------------------------------------

0x8005=1000 0000 0000 0101B 

0xA001=1010 0000 0000 0001B

对比两个二进制高低位正好是完全相反的,CRC校验分为正向校验与反向校验。正向校验高位在左,反向校验低位在左

正向校验使用左移位,反向校验使用右移位

---------------------------------

Modbus协议,常规485通讯的信息发送形式如下:

地址 功能码 数据信息 校验码

1byte 1byte nbyte 2byte

CRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。

例如:信息字段代码为: 1011001,校验字段为:1010。

发送方:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10

 

参考文档:

 https://www.jianshu.com/p/676744381473

https://www.jianshu.com/p/c0d93c2e89ce

VB对应的算法

Public Function CRC16(Data() As Byte, ByRef bLow As Byte, ByRef bHigh As Byte) As String

    Dim CRC16Lo As Byte, CRC16Hi As Byte      CRC寄存器
    Dim CL As Byte, ch As Byte                多项式码&HA001
    Dim SaveHi As Byte, SaveLo As Byte
    Dim i As Integer
    Dim flag As Integer
    CRC16Lo = &HFF
    CRC16Hi = &HFF
    CL = 1
    ch = &HA0
    
    For i = LBound(Data) To UBound(Data) - 2
        CRC16Lo = CRC16Lo Xor Data(i) 每一个数据与CRC寄存器的低8位进行异或
        右移8次
        For flag = 0 To 7
            记录一下,用来判断移出位是0还是1
            SaveHi = CRC16Hi
            SaveLo = CRC16Lo
            
            CRC16Hi = CRC16Hi  2            高位右移一位
            CRC16Lo = CRC16Lo  2            低位右移一位
            
            If ((SaveHi And &H1) = &H1) Then 如果高位字节最后一位为1
                CRC16Lo = CRC16Lo Or &H80      则低位字节右移后前面补1
            End If                           否则自动补0
            
            If ((SaveLo And &H1) = &H1) Then 如果移出位为1,则与多项式码进行异或
                CRC16Hi = CRC16Hi Xor ch
                CRC16Lo = CRC16Lo Xor CL
            End If
        Next flag
    Next i
    Dim ReturnData(1) As Byte
    ReturnData(0) = CRC16Hi              CRC高位
    ReturnData(1) = CRC16Lo              CRC低位
    Dim Value As Double
    Value = CLng(CRC16Hi * 256) + CRC16Lo
    CRC16 = ReturnData
    bHigh = CRC16Hi
    bLow = CRC16Lo


End Function

 

C# 对应的算法

        public static byte[] CRC16(byte[] data)
        {
            int len = data.Length;
            if (len > 0)
            {
                ushort crc = 0xFFFF;

                for (int i = 0; i < len; i++)
                {
                    crc = (ushort)(crc ^ (data[i]));
                    for (int j = 0; j < 8; j++)
                    {
                        crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
                    }
                    System.Diagnostics.Debug.WriteLine("i=" + i.ToString() + ","+ crc.ToString());
                }
                byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
                byte lo = (byte)(crc & 0x00FF); //低位置

                return new byte[] { hi, lo };
            }
            return new byte[] { 0, 0 };
        }

 

以上是关于Modbus协议 CRC 校验码的主要内容,如果未能解决你的问题,请参考以下文章

modbus协议CRC校验计算方式?该怎么计算?

MODBUS通讯CRC校验码怎么算,有那位能告诉我呀

如何计算modbus-rtu的crc校验码

Modbus RTU CRC校验码计算方法

modbus协议之串行链路

Java Modbus CRC16校验