Hier meine Modifikation des Originalbausteins:
Folgende Änderungen wurden vorgenommen
*) Die Nummer des geprüften Datenbausteins muss nicht mehr im FUP untauglichen Pointerformat eingegeben werden, sondern als integerzahl.
*) CRC Parameter sind bereits standardmässig vorbelegt, und in den Stationären Bereich verschoben worden, damit diese nicht jedesmal neu eingegeben werden müssen
*) Baustein gibt zusätzlich zur Prüfsumme auch die Anzahl der Bytes des geprüften Bausteins aus
---------------------- Programm -----------------
FUNCTION_BLOCK sys_fb_crc
TITLE = 'sys_fb_crc'
//
//CRC_GEN generates a CRC checksum from a block of data and returns the checksum in a DWORD to be connected to the data for transmission.
//the CRC Polynom is specified with the config variable PN and the length of the Polynom is specified by PL
//A Polynom x4 + X + 1 is represented by 0011 with length 4, the highest order bit is not specified at all..
//The input data is an array of byte of any size, the function is called by CRC_GEN(ADR(array),SIZEOF(array), ....).
//
//uses: REVERSE (FC310)
// REFLECT (FC426)
//
VERSION : '0.1'
AUTHOR : ed_u_hug
NAME : crc
FAMILY : LOGIC
VAR_INPUT //IN
db_nr: INT;
END_VAR
VAR_OUTPUT //OUT
CRC_GEN : DWORD;
_CRC_GEN AT CRC_GEN : ARRAY[0..31] OF BOOL;
datenanzahl_byte : INT;
END_VAR
VAR //STATIC
PL : INT :=32;
PN : DWORD :=DW#16#4C11DB7;
INIT : DWORD :=DW#16#FFFFFFFF;
REV_IN : BOOL :=true;
REV_OUT : BOOL:=true;
XOR_OUT : DWORD :=DW#16#FFFFFFFF;
END_VAR
VAR_TEMP //TEMP
pos : INT;
shift : INT;
dx: BYTE;
_dx AT dx : ARRAY[0..7] OF BOOL;
bits: INT;
rTEST_DB: INT;
Adr: INT;
DB_LENGTH: WORD;
WRITE_PROT: BOOL;
END_VAR
BEGIN
(* Datenbaustein Testen *)
rTEST_DB := TEST_DB(DB_NUMBER := INT_TO_WORD(db_nr) // IN: WORD
,DB_LENGTH := DB_LENGTH // OUT: WORD
,WRITE_PROT := WRITE_PROT // OUT: BOOL
); // INT
(* Ende wenn Test-DB <> 0 = Fehler *)
IF rTEST_DB <> 0 THEN RETURN; END_IF;
(* Ende wenn DB zu klein *)
datenanzahl_byte:=WORD_TO_INT(DB_LENGTH);
IF datenanzahl_byte < 4 THEN RETURN; END_IF;
Adr := 0;
(* align polygon *)
shift := 32 - PL;
PN := SHL(IN:=PN,N:=shift);
(* load first 4 bytes into register minimum message size is 4 bytes
for smaller messages fill with 0#s at the beginning*)
FOR pos := 0 TO 3 DO
IF REV_IN THEN CRC_GEN := SHL(IN:=CRC_GEN,N:=8) OR REVERSE(WORD_TO_BLOCK_DB(INT_TO_WORD(db_nr)).DB[Adr+Pos]); ELSE CRC_GEN := SHL(IN:=CRC_GEN,N:=8) OR WORD_TO_BLOCK_DB(INT_TO_WORD(db_nr)).DB[Adr+pos]; END_IF;
END_FOR;
pos := 4;
(* xor with init value *)
CRC_GEN := CRC_GEN XOR SHL(IN:=init,N:=shift);
(* calculate CRC for each byte *)
WHILE pos < datenanzahl_byte DO
IF REV_IN THEN DX := REVERSE(WORD_TO_BLOCK_DB(INT_TO_WORD(db_nr)).DB[Adr+pos]); ELSE DX := WORD_TO_BLOCK_DB(INT_TO_WORD(db_nr)).DB[Adr+pos]; END_IF;
pos := pos + 1;
(* crc calculation for one byte *)
FOR bits := 0 TO 7 DO
IF _CRC_GEN[7] THEN
CRC_GEN := (SHL(IN:=CRC_GEN,N:=1) OR BOOL_TO_DWORD(_DX[7])) XOR PN;
ELSE
CRC_GEN := SHL(IN:=CRC_GEN,N:=1) OR BOOL_TO_DWORD(_DX[7]);
END_IF;
dx := SHL(IN:=dx,N:=1);
END_FOR;
END_WHILE;
(* all bytes are processed, need to finish the registers 32 bits *)
FOR bits := 0 TO 31 DO
IF _CRC_GEN[7] THEN
CRC_GEN := (SHL(IN:=CRC_GEN,N:=1) OR BOOL_TO_DWORD(_DX[7])) XOR PN;
ELSE
CRC_GEN := SHL(IN:=CRC_GEN,N:=1) OR BOOL_TO_DWORD(_DX[7]);
END_IF;
END_FOR;
(* final XOR *)
CRC_GEN := SHR(IN:=CRC_GEN,N:=shift) XOR XOR_OUT;
(* reverse the crc_out put if necessary *)
IF REV_OUT THEN CRC_GEN := REFLECT(D:=CRC_GEN,L:=PL); END_IF;
(* typical crc polynoms
CRC-4-ITU x4 + x + 1 (ITU G.704, p. 12) 0x3 or 0xC (0x9)
CRC-5-ITU x5 + x4 + x2 + 1 (ITU G.704, p. 9) 0x15 or 0x15 (0x0B) Bluetooth
CRC-5-USB x5 + x2 + 1 (use: USB token packets) 0x05 or 0x14 (0x9)
CRC-6-ITU x6 + x + 1 (ITU G.704, p. 3) 0x03 or 0x30 (0x21)
CRC-7 x7 + x3 + 1 (use: telecom systems, MMC) 0x09 or 0x48 (0x11)
CRC-8-ATM x8 + x2 + x + 1 (use: ATM HEC) 0x07 or 0xE0 (0xC1)
CRC-8-CCITT x8 + x7 + x3 + x2 + 1 (use: 1-Wire bus) 0x8D or 0xB1 (0x63)
CRC-8-Dallas/Maxim x8 + x5 + x4 + 1 (use: 1-Wire bus) 0x31 or 0x8C (0x19)
CRC-8 x8 + x7 + x6 + x4 + x2 + 1 0xD5 or 0xAB (0x57)
CRC-8-SAE J1850 x8 + x4 + x3 + x2 + 1 0x1D or 0xB8
CRC-10 x10 + x9 + x5 + x4 + x + 1 0x233 or 0x331 (0x263)
CRC-12 x12 + x11 + x3 + x2 + x + 1 (use: telecom systems) 0x80F or 0xF01 (0xE03)
CRC-15-CAN x15 + x14 + x10 + x8 + x7 + x4 + x3 + 1 0x4599 or 0x4CD1 (0x19A3)
CRC-16-Fletcher Not a CRC; see Fletcher's checksum Used in Adler-32 A & B CRCs
CRC-16-CCITT x16 + x12 + x5 + 1 (XMODEM,X.25, V.41, Bluetooth, PPP, IrDA; known as "CRC-CCITT") 0x1021 or 0x8408 (0x0811)
CRC-16-IBM x16 + x15 + x2 + 1 (USB, many others; also known as "CRC-16") 0x8005 or 0xA001 (0x4003)
CRC-24-Radix-64 x24 + x23 + x18 + x17 + x14 + x11 + x10 + x7 + x6 + x5 + x4 + x3 + x + 1 0x864CFB or 0xDF3261 (0xBE64C3)
CRC-32-Adler Not a CRC; see Adler-32 See Adler-32
CRC-32-MPEG2 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 0x04C11DB7 or 0xEDB88320 (0xDB710641) Also used in IEEE 802.3
CRC-32-IEEE 802.3 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 (V.42) 0x04C11DB7 or 0xEDB88320 (0xDB710641)
CRC-32C (Castagnoli) x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1 0x1EDC6F41 or 0x82F63B78 (0x05EC76F1)
CRC-64-ISO x64 + x4 + x3 + x + 1 (use: ISO 3309) 0x000000000000001B or 0xD800000000000000 (0xB000000000000001)
CRC-64-ECMA-182 x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 + x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 + x10 + x9 + x7 + x4 + x + 1
(as described in ECMA-182 p.63) 0x42F0E1EBA9EA3693 or 0xC96C5795D7870F42 (0x92D8AF2BAF0E1E85)
*)
(* revision history
hm 9.6.2007 rev 1.0
original version
hm 11.9.2007 rev 1.1
deleted unused variable i
hm 9. oct 2007 rev 1.2
added init code for crc and xor_out
added refelct in and reflect_out (rev_in und Rev_out)
hm 2. jan 2008 rev 1.3
small changes for performance improvements
hm 16. mar. 2008 rev 1.4
changed type of input size to uint
hm 10. mar. 2009 rev 1.5
removed nested comments
hm 16. jan. 2011 rev 2.0
new version
*)
END_FUNCTION_BLOCK