Просмотр полной версии : CRC-16/ARC помогите перевести с С++ на мэк
Gvenihvivar
02.07.2014, 11:39
Добрый день.
Помогите перевести код CRC-16/ARC с С++
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
static uint16_t CRC16_ARC(uint8_t *data, size_t len) {
uint16_t crc = 0x0000;
size_t j;
int i;
// Note: 0xA001 is the reflection of 0x8005
for (j=len; j>0; j--) {
crc ^= *data++;
for (i=0; i<8; i++) {
if (crc & 1) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return (crc);
}
У меня получилось следующее
var
data : POINTER TO BYTE;
SIZE : INT;
j: INT;
i: INT;
crc : WORD:=16#0000;
arr: array [0..3] of byte:= [10,11,12,13];
end_var
data :=ADR(arr[0]);
size :=4;
FOR j:=size TO 0 BY -1 DO
crc := data^;
FOR i:=0 TO 8 DO
IF WORD_TO_BOOL(crc AND 16#0001) THEN crc:= ( SHR(crc, 1) OR 16#A001);
ELSE crc := SHR(crc, 1); END_IF
END_FOR
data:=data + SIZEOF(data^);
END_FOR
crc16ROCplus_1 := crc;
должно получиться A819, но не получается. Помогите найти ошибку.
Сразу вижу, что вместо FOR i:=0 TO 8 DO, должно быть FOR i:=0 TO 7 DO
Gvenihvivar
02.07.2014, 11:56
тогда вместо FOR j:=size TO 0 BY -1 DO должно быть FOR j:=size-1 TO 0 BY -1 DO или FOR j:=size TO 1 BY -1 DO
но все равно не сходится
тогда вместо FOR j:=size TO 0 BY -1 DO должно быть FOR j:=size-1 TO 0 BY -1 DO или FOR j:=size TO 1 BY -1 DO
но все равно не сходится
Значит еще есть ошибки. Зачем вообще копировать код C++, ведь алгоритм расчета хорошо описан. Я в свое время по этому алгоритму свой код написал и все у меня срослось.
Gvenihvivar
02.07.2014, 12:08
Я не против использовать уже написанный код, просто я нашла только это для расчета контрольной суммы roc протокола.
Я не против использовать уже написанный код, просто я нашла только это для расчета контрольной суммы roc протокола.
Какого протокола ?
Дмитрий Егоренков
02.07.2014, 12:24
( SHR(crc, 1) XOR 16#A001)
Gvenihvivar
02.07.2014, 12:40
XOR еще нужен в строке crc ^= *data++; , там же crc = crc ^ *data++; То есть crc := crc xor data^;
Теперь все сходиться, я там немного ошиблась с суммой, правильный ответ dfb6
Рабочий код. Контрольная сумма по протоколу ROC+ для плк ROC809
data:=ADR(arr[0]);
size:=4;
FOR j:=size TO 1 BY -1 DO
crc := crc xor data^;
FOR i:=0 TO 7 DO
IF WORD_TO_BOOL(crc AND 16#0001) THEN crc:= ( SHR(crc, 1) XOR 16#A001);
ELSE crc := SHR(crc, 1); END_IF
END_FOR
data:=data + SIZEOF(data^);
END_FOR
crc16ROCplus_1 := crc;
Всем большое спасибо!
А почем этот ROC809, наверное, жутко дорогой ?
Gvenihvivar
02.07.2014, 12:52
точной цены не знаю, но удовольствие это не из дешевых
Вот этот кусок
IF WORD_TO_BOOL(crc AND 16#0001) THEN crc:= ( SHR(crc, 1) XOR 16#A001);
ELSE crc := SHR(crc, 1); END_IF... можно упростить:
crc := SHR(crc, 1) XOR 16#A001 * BOOL_TO_WORD(crc.0);
Gvenihvivar
02.07.2014, 13:53
У умножения приоритет больше чем у XOR?
Без скобок проблем не будет?
Так и надо, чтобы сначала умножалось. Я проверил, если что.
Кстати для прикола вообще без ветвлений в один цикл переписал:
FOR j := 0 TO size * 8 - 1 DO
crc := crc XOR arr[j / 8] * BOOL_TO_WORD(j MOD 8 = 0);
crc := SHR(crc, 1) XOR (16#A001 * BOOL_TO_WORD(crc.0));
END_FORТоже проверил. Компактнее, но медленнее (много бесполезного ксора с нулём).
http://www.owen.ru/forum/showthread.php?t=17523
Может поможет, там тоже был алгоритм на Си и вариант на ST того же кода.
а если заглянуть в бибку ОСКАТ, то там есть готовый блок расчета любых контрольных сумм
Gvenihvivar
03.07.2014, 10:14
да, знаю, но там много лишнего. Он ведь универсален для всего на свете.
да, знаю, но там много лишнего. Он ведь универсален для всего на свете.
так кто мешает, лишнее убрать, там практически вся универсальность заключается в числе ограничивающем по модулю
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot