Я пытаюсь преобразовать функцию C в PHP, который выполняет 8-битное вычисление CRC.
Оригинальный код C:
uint8_t CRCCalc (uint8_t* pointer, uint16_t len) {
uint8_t CRC = 0x00;
uint16_t tmp;
while(len > 0) {
tmp = CRC << 1;
tmp += *pointer;
CRC = (tmp & 0xFF) + (tmp >> 8);
pointer++;
--len;
}
return CRC;
}
PHP-код, который я придумал:
function crc8_calc($hex_string)
{
$bin_data = pack('H*',$hex_string);
$bin_length = strlen($bin_data);
$CRC = 0x00;
$pos = 0;
while($bin_length>0)
{
//$pos = $CRC << 1;
$CRC = ($bin_data[$pos] & 0xFF) + ($bin_data[$pos] >> 8);
$bin_length --;
$pos++ ;
}
return $CRC;
}
Есть что-то, чего не хватает, так как результаты функций PHP неверны. Я не очень знаком с C, поэтому не уверен, что мое преобразование правильное. Функция C выдает правильный CRC
Например, если шестнадцатеричное представление строки:
280500000805151001240000000010017475260004041001372068828503000000000000
КПР должен быть D4.
Я уже видел следующие ссылки для расчета CRC8, но мне кажется, что-то не хватает
как сгенерировать 8bit CRC в PHP
CRC8-проверка в PHP
Из этого ответа я также взял несколько бит моего кода преобразования
Конвертировать C в PHP для функции CRC16
Попробуйте это так:
function crc8_calc($hex_string)
{
$bin_data = pack('H*',$hex_string);
$bin_length = strlen($bin_data);
$CRC = 0;
$tmp = 0;
$pos = 0;
while($bin_length>0)
{
$tmp = $CRC << 1;
$tmp = $tmp + ord($bin_data[$pos]); //Added ord
$CRC = ($tmp + ($tmp >> 8)) & 0xFF;
$bin_length --;
$pos++ ;
}
return $CRC;
}
Очевидно, что два фрагмента кода не делают одно и то же. В функции C первое, что происходит: вы сдвигаете CRC (который вы уже рассчитали) влево на 1 бит (то же самое, что умножаете его на 2), затем добавляете следующий байт из массива и затем пересчитываете CRC, сложив вместе два байта tmp.
Ваш пример PHP не выполняет начальный сдвиг и не смешивает предыдущую версию CRC с вычислением для следующего байта.
($tmp & 0xFF)
просто младший байт
($tmp >> 8)
сдвиг вправо 8
Я не проверял, но это быстрая попытка.
function CRCCalc ($value, $len) {
$CRC = 0;
while($len > 0) {
$tmp = $CRC << 1; // shift left 1
$tmp += $value;
$CRC = ($tmp & 0xFF) + ($tmp >> 8); // ($tmp & 0xFF) just lower byte ($tmp >> 8: shift right 8
$value++;
$len--;
}
return $CRC;
}