• 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 };
            }
  • 相关阅读:
    JDK源码之Thread 类分析
    java中符号类型和无符号类型的问题分析
    国内高速Maven仓库
    Idea Live Templates代码模板
    正则表达式
    java内存泄漏
    MySQL查看 InnoDB表中每个索引的高度
    ThreadLocalMap里Entry为何声明为WeakReference?
    Java JDBC中,MySQL字段类型到JAVA类型的转换
    MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现
  • 原文地址:https://www.cnblogs.com/zitjubiz/p/modbus_crc16.html
Copyright © 2020-2023  润新知