zoukankan      html  css  js  c++  java
  • 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 };
            }
  • 相关阅读:
    SQL Server常用到的几个设置选项
    动态加载母版页
    Sql查询技巧
    【WP7】关于磁贴的使用
    ashx,页面一般情况下不能方法session,必须添加两个接口。才能访问session。 狼
    悟头javascript学习笔记 狼
    IIS处理简介, IHttpHandler ,IHttpModel 狼
    在IIS下,不能执行exe文件解决办法。 狼
    给Ubuntu右键快捷菜单添加终端栏目
    VC 单文档程序 隐藏程序及任务栏图标
  • 原文地址:https://www.cnblogs.com/zitjubiz/p/modbus_crc16.html
Copyright © 2011-2022 走看看