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 };
        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM