PDA

Просмотр полной версии : Расчёт CRC16-CCITT



Андрей007
21.01.2013, 10:56
Помогите правильно перевести с языка Си или Си++ на язык ST в CoDeSys 2 следующую программу расчёта CRC16-CCITT.
http://img-fotki.yandex.ru/get/4127/72252628.0/0_95d15_b74bf252_XXXL.jpg

kgsh82
21.01.2013, 12:52
Посмотрите в примерах и полезностях - есть уже готовое

kgsh82
21.01.2013, 12:55
Вернее очень похожее

Андрей007
21.01.2013, 13:38
Мне нужно не похожее, а точный перевод на ST.
Похожее я видел.
CRC8 на языке ST у меня получилось написать, а c CRC16
какая-то лобуда выходит.

petera
21.01.2013, 15:24
Уже все придумано до нас используйте OSCATBasic CRC_GEN
Рассчитывает штук 50 различных видов
Я описание ФБ CRC_GEN выкладывал здесь,
http://www.owen.ru/forum/showpost.php?p=99084&postcount=4
Там в документе (во вложении) приведены какие данные в настойке этого ФБ нужны для каждого вида CRC
Настройки
PL : UINT (Длина полинома)
PN : DWORD (Полином)
INIT : DWORD (Данные для инициализации)
REV_IN : BOOL (Переставлять местами биты в байтах на входе)
REV_OUT : BOOL (Переставлять местами биты в байтах на выходе)
XOR_OUT : DWORD (Последнее XOR результата)

capzap
21.01.2013, 15:26
FUNCTION CRC_GEN : DWORD

VAR_INPUT
PT : POINTER TO ARRAY[0..32000] OF BYTE;
SIZE : INT;
PL : INT;
PN : DWORD;
INIT : DWORD;
REV_IN : BOOL;
REV_OUT : BOOL;
XOR_OUT : DWORD;
END_VAR
VAR
pos : INT;
shift : INT;
dx: BYTE;
bits: INT;
END_VAR

(* align polygon *)
shift := 32 - PL;
PN := SHL(PN, 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(CRC_GEN, 8) OR REVERSE(PT^[pos]); ELSE CRC_GEN := SHL(CRC_GEN, 8) OR PT^[pos]; END_IF;
END_FOR;
pos := 4;

(* xor with init value *)
CRC_GEN := CRC_GEN XOR SHL(init, shift);

(* calculate CRC for each byte *)
WHILE pos < size DO
IF REV_IN THEN DX := REVERSE(PT^[pos]); ELSE DX := PT^[pos]; END_IF;
pos := pos + 1;
(* crc calculation for one byte *)
FOR bits := 0 TO 7 DO
IF CRC_GEN.31 THEN
CRC_GEN := (SHL(CRC_GEN, 1) OR BOOL_TO_DWORD(DX.7)) XOR PN;
ELSE
CRC_GEN := SHL(CRC_GEN, 1) OR BOOL_TO_DWORD(DX.7);
END_IF;
dx := SHL(dx, 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.31 THEN
CRC_GEN := (SHL(CRC_GEN, 1) OR BOOL_TO_DWORD(DX.7)) XOR PN;
ELSE
CRC_GEN := SHL(CRC_GEN, 1) OR BOOL_TO_DWORD(DX.7);
END_IF;
END_FOR;

(* final XOR *)
CRC_GEN := SHR(CRC_GEN, shift) XOR XOR_OUT;

(* reverse the crc_out put if necessary *)
IF REV_OUT THEN CRC_GEN := REFLECT(CRC_GEN, 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)
*)




FUNCTION MB_CRC : WORD
VAR_INPUT
pData: POINTER TO BYTE; (* указатель на блок данных *)
Size: WORD; (* размер блока данных *)
END_VAR
VAR
Cnt: BYTE; (* счетчик битов *)
END_VAR

(* Вычисление контрольной суммы кадра MODBUS RTU CRC *)
MB_CRC := 16#FFFF;
WHILE Size > 0 DO
MB_CRC := MB_CRC XOR pData^;
FOR Cnt := 0 TO 7 DO
IF MB_CRC.0 = 0 THEN
MB_CRC := SHR(MB_CRC, 1);
ELSE
MB_CRC := SHR(MB_CRC, 1) XOR 16#A001;
END_IF
END_FOR;
pData := pData + 1;
Size := Size - 1;
END_WHILE

куча блоков в свободном доступе для расчета КС

Андрей007
22.01.2013, 13:17
Спасибо конечно, за внимание и за ссылки, но мне бы
на мой вопрос ответ получить.

Через библиотеку OSCAT я пробовал посчитать, там другая цифра получается (не сходится с примером данным в инструкции к прибору).

Если кто-нибудь разбирается, переведите пожалуйста с языка С на ST в CoDeSys.

Заранее спасибо!

capzap
22.01.2013, 14:29
Спасибо конечно, за внимание и за ссылки, но мне бы
на мой вопрос ответ получить.

Через библиотеку OSCAT я пробовал посчитать, там другая цифра получается (не сходится с примером данным в инструкции к прибору).

Если кто-нибудь разбирается, переведите пожалуйста с языка С на ST в CoDeSys.

Заранее спасибо!

да Вы не ответ на вопрос уже спрашиваете а готовое решение, чтоб за Вас сделали, наглеть то не надо
В оскате дан Ваш полином
CRC-16-CCITT x16 + x12 + x5 + 1 (XMODEM,X.25, V.41, Bluetooth, PPP, IrDA; known as "CRC-CCITT") 0x1021 or 0x8408 (0x0811)значит код рабочий, можно и код с модбасом расширить количество бит до 16 и так же полином соответствующий вставить, Вам нужно Вы и решайте

Андрей007
22.01.2013, 15:19
А я лично у тебя ни чего не прошу.
Нет желания помочь зачем вообще пишешь?

capzap
22.01.2013, 15:28
пишу, чтоб такие как Вы "зад свой подняли" и начали работать

Андрей007
22.01.2013, 15:41
Тебе что нужно? Быдлятник тут развёл!

Зачем ты вообще тут тролишь?

stskr
07.11.2014, 11:16
Недавно столкнулся с такой задачей.
Оказалось, что функция из библиотеки OSCAT работает корректно только с данными кратными 4 байт.
Поскольку у меня могут быть посылки размером 2 и 3 байта, то написал свою функцию расчета CRC.
Напишите, если нужно, - приведу здесь код.

Здесь приведены алгоритмы расчета CRC:
http://tinyurl.com/mkjtn72

А этот калькулятор правильно считает CRC:
http://www.lammertbies.nl/comm/info/crc-calculation.html