2016-07-22 155 views
0

你好,我已經對算法中的Modbus CRC16,但我不知道我怎麼會叫它和使用,Delphi中如何使用Crc16 ModBus?

CONST table: ARRAY[0..255] OF WORD = 
     ($0000,$C0C1,$C181,$0140,$C301,$03C0,$0280,$C241,$C601,$06C0,$0780, 
     $C741,$0500,$C5C1,$C481,$0440,$CC01,$0CC0,$0D80,$CD41,$0F00,$CFC1, 
     $CE81,$0E40,$0A00,$CAC1,$CB81,$0B40,$C901,$09C0,$0880,$C841,$D801, 
     $18C0,$1980,$D941,$1B00,$DBC1,$DA81,$1A40,$1E00,$DEC1,$DF81,$1F40, 
     $DD01,$1DC0,$1C80,$DC41,$1400,$D4C1,$D581,$1540,$D701,$17C0,$1680, 
     $D641,$D201,$12C0,$1380,$D341,$1100,$D1C1,$D081,$1040,$F001,$30C0, 
     $3180,$F141,$3300,$F3C1,$F281,$3240,$3600,$F6C1,$F781,$3740,$F501, 
     $35C0,$3480,$F441,$3C00,$FCC1,$FD81,$3D40,$FF01,$3FC0,$3E80,$FE41, 
     $FA01,$3AC0,$3B80,$FB41,$3900,$F9C1,$F881,$3840,$2800,$E8C1,$E981, 
     $2940,$EB01,$2BC0,$2A80,$EA41,$EE01,$2EC0,$2F80,$EF41,$2D00,$EDC1, 
     $EC81,$2C40,$E401,$24C0,$2580,$E541,$2700,$E7C1,$E681,$2640,$2200, 
     $E2C1,$E381,$2340,$E101,$21C0,$2080,$E041,$A001,$60C0,$6180,$A141, 
     $6300,$A3C1,$A281,$6240,$6600,$A6C1,$A781,$6740,$A501,$65C0,$6480, 
     $A441,$6C00,$ACC1,$AD81,$6D40,$AF01,$6FC0,$6E80,$AE41,$AA01,$6AC0, 
     $6B80,$AB41,$6900,$A9C1,$A881,$6840,$7800,$B8C1,$B981,$7940,$BB01, 
     $7BC0,$7A80,$BA41,$BE01,$7EC0,$7F80,$BF41,$7D00,$BDC1,$BC81,$7C40, 
     $B401,$74C0,$7580,$B541,$7700,$B7C1,$B681,$7640,$7200,$B2C1,$B381, 
     $7340,$B101,$71C0,$7080,$B041,$5000,$90C1,$9181,$5140,$9301,$53C0, 
     $5280,$9241,$9601,$56C0,$5780,$9741,$5500,$95C1,$9481,$5440,$9C01, 
     $5CC0,$5D80,$9D41,$5F00,$9FC1,$9E81,$5E40,$5A00,$9AC1,$9B81,$5B40, 
     $9901,$59C0,$5880,$9841,$8801,$48C0,$4980,$8941,$4B00,$8BC1,$8A81, 
     $4A40,$4E00,$8EC1,$8F81,$4F40,$8D01,$4DC0,$4C80,$8C41,$4400,$84C1, 
     $8581,$4540,$8701,$47C0,$4680,$8641,$8201,$42C0,$4380,$8341,$4100, 
     $81C1,$8081,$4040); 

PROCEDURE CalcCRC16 (p: pByte; nbyte: WORD; VAR CRCvalue: WORD); 
VAR i: WORD; 
q: pByte; 
BEGIN 
    q := p; 
    FOR i := 1 TO nBYTE DO 
    BEGIN 
     CRCvalue := Hi(CRCvalue) XOR Table[ q^ XOR Lo(CRCvalue) ]; 
     INC(q) 
    END; 
END; 

7E 00 00 00 00 74 00 01 5E 5A 02 20 70 11 15 20 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

for這些字節應該回應爲「79 B7」

謝謝推進每個人和Stack Overflow團隊!

回答

1

這個謎題有三個缺失的部分。首先,您需要知道CRCValue的初始值以傳遞給CalcCRC16。對於Modbus CRC-16,該值爲$ FFFF,如found herehere

其次,你需要知道什麼來計算CRC over。消息中的所有字節?他們的連續子集?哪個子集?爲此,您需要參考您正在使用的格式的一些文檔。

第三,CRC如何存儲在流中?大端或小端?那麼你的79 b7,大概來自流,意味着16位值79b7b779?再次您將不得不參考文檔。

搜索消息的所有可能的連續子集都不會產生16位CRC。您可能錯誤地在消息中標識了CRC本身的位置。

+0

您好,感謝您的回答,這我不好,對不起,7E第一個前綴,所以:CRC從:00 00 00 00 74 00 01 5E 5A 02 20 70 11 15 20 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00> b9 79 crc –

+0

所以在b7之前。現在是b9。這是什麼?在任何情況下,任何一個數據子集都不能以任何順序匹配任何一個CRC。 –

+0

泰克斯回答,我找到解決方案,http://i.hizliresim.com/2ZB8jE.png,我與其他前綴我不好,試試.....再次感謝。 –

0
**Original Code from Sky devil** 
------------------------------- 
function GetModbusCRC16(const HexData: string): UInt16; 
var 
Buffer: Array of Byte; //TArray<Byte>; 
CRC: UInt16; 
Mask: UInt16; 
I: Integer; 
J: Integer; 
begin 
SetLength(Buffer, Length(HexData) div 2); 
HexToBin(PChar(HexData), Buffer, Length(Buffer)); 

CRC := $FFFF; 
for I := Low(Buffer) to High(Buffer) do 
begin 
CRC := CRC xor Buffer; 
for J := 1 to 8 do 
begin 
Mask := 0; 
if ((CRC/2) <> (CRC div 2)) then 
begin 
Mask := $A001; 
end; 
CRC := (CRC div 2) and $7FFF; 
CRC := CRC xor Mask; 
end; 
end; 

//--------------------------------------------------------- Swap result 
//Result := CRC; <- comment this 
// Swap lo/hi 
Result := ((CRC and $FF) shl 8) + (CRC shr 8); 
end; 


var 
C: UInt16; 
S: string; 

begin 
C := GetModbusCRC16('01030400000060'); 
S := IntToHex(C,4); // <- $FA1B 
end; 


**VB version original from internet**: 
------------------------------------ 

Sub getCRC16_Modbus() 
    Dim x As Long 
    Dim mask, i, j, nC, Crc As Integer 
    Dim c As String 
    Dim txt As String 

    txt = "01030400000060" 

    Crc = &HFFFF ' crc mit $ffff initalisieren 

    For nC = 1 To Len(txt) Step 2 
     j = Val("&H" + Mid(txt, nC, 2)) 'im HEX-Format 
     Crc = Crc Xor j 
     For j = 1 To 8 
      mask = 0 
      If Crc/2 <> Int(Crc/2) Then mask = &HA001 
      Crc = Int(Crc/2) And &H7FFF : Crc = Crc Xor mask 
     Next j 
    Next nC 

    txt = Hex$(Crc) 'Checksumme 

    Label1.Text = txt 

End Sub 
+1

當他們提供關於如何以及爲什麼提供的代碼回答問題的簡短解釋時,答案是最有用的。 –