vba — CRC Maxim / Dallas 1Wire Generation: преобразование Visual Basic в переполнение стека

Мне нужна функция, которая генерирует Maxim / Dallas 1-Wire CRC 8bit-Code, как эта страница:
http://www.datastat.com/sysadminjournal/maximcrc.cgi

Для этой проблемы я нашел маленький калькулятор Excel для решения.
Он работает правильно, но у меня есть проблема, чтобы перевести его на язык PHP.

Оригинальный код VB:

Private Sub ROMCRC_Click()

Dim InHex, OutBinStr As String
Dim OutBinArr(1 To 56) As Integer
Dim OutDec, i, CRC(1 To 8), CRCTemp As Integer

InHex = Range("ROMByte1").Value & Range("ROMByte2").Value & Range("ROMByte3").Value & Range("ROMByte4").Value & Range("ROMByte5").Value & Range("ROMByte6").Value & Range("ROMByte7").Value
OutBinStr = HexToBin(InHex)

' Convert string to array, LSB = OutBinArr(1)
For i = 1 To 56
OutBinArr(57 - i) = Mid$(OutBinStr, i, 1) ' Split(OutBinStr)
Next i

'Initialize CRC
For i = 1 To 8
CRC(i) = 0
Next i

'Calculate CRC
For i = 1 To 56
CRCTemp = CRC(1) Xor OutBinArr(i)
CRC(1) = CRC(2)
CRC(2) = CRC(3)
CRC(3) = CRC(4) Xor CRCTemp
CRC(4) = CRC(5) Xor CRCTemp
CRC(5) = CRC(6)
CRC(6) = CRC(7)
CRC(7) = CRC(8)
CRC(8) = CRCTemp
Next i

DecCRC = BinToDec(CRC)

Range("ROMCRCValue").Value = DecCRC

End SubPrivate Function HexToBin(hstr)
'convert hex string to binary string
cnvarr = Array("0000", "0001", "0010", "0011", _
"0100", "0101", "0110", "0111", "1000", _
"1001", "1010", "1011", "1100", "1101", _
"1110", "1111")
bstr = ""For i = 1 To Len(hstr)
hdgt = Mid(hstr, i, 1)
cix = CInt("&H" & hdgt)
bstr = bstr & cnvarr(cix)
Next
HexToBin = bstr
End Function

Function BinToDec(bstr)
'convert 8 bit Binary number to Decimal
Dim j, Out As Integer

Out = 0
For j = 1 To 8
Out = Out + bstr(j) * 2 ^ (j - 1)
Next j

BinToDec = Out
End Function

Мой тестовый код PHP:

protected function HexToBin($hstr) {
//convert hex string to binary string
$cnvarr = array(
'0000',
'0001',
'0010',
'0011',
'0100',
'0101',
'0110',
'0111',
'1000',
'1001',
'1010',
'1011',
'1100',
'1101',
'1110',
'1111'
);
$bstr = "";
for ($i = 1; $i <= strlen($hstr); $i++) {
$hdgt = substr($hstr, $i, 1);
$cix = intval($hdgt);
echo $cix.'|';
$bstr .= $cnvarr[$cix];
}
return $bstr;
}

protected function createHash($data) {
//$OutBinStr = $this->HexToBin($data);
$OutBinStr = hex2bin($data);

$OutBinArr = array();
$crc = array();

//Convert string to array, LSB = OutBinArr(1)
for ($i = 1; $i <= 56; $i++) {
$OutBinArr[57 - $i] = substr($OutBinStr, $i - 1, 1);
}

//initialize crc
for ($i = 1; $i <= 8; $i++) {
$crc[$i] = 0;
}

// calculate
for ($i = 1; $i <= 56; $i++) {

$CRCTemp = $crc[1] ^ $OutBinArr[$i];
$crc[1] = $crc[2];
$crc[2] = $crc[3];
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5] ^ $CRCTemp;
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $crc[8];
$crc[8] = $CRCTemp;
}

return implode('', $crc);
}

Пример вызова:

$buttonId = '0000145D6E0F01';
echo $this->createHash($buttonId);

Я благодарю вас, если у вас есть идеи, почему сценарий не генерирует правильный CRC.

Спасибо, привет
Майкл

1

Решение

Ваш HexToBin() генерировал неправильную строку. for цикл для substr() началось с 1 вместо 0. См. Руководство Subr.

В результате взрыва $ crc получилось обратное значение битового порядка.

<?PHP
function HexToBin($hstr){
$hstr = str_replace(' ','',$hstr);
$hArr = str_split($hstr);
$bstr = "";
foreach($hArr AS $c){
$cix = sprintf("0x0{$c}");
// echo sprintf("%04b|",hexdec($cix));
$bstr .= sprintf("%04b",hexdec($cix));
}

return $bstr;
}

function createHash($data){
$OutBinStr = HexToBin($data);
$crc = array_fill(0,8,0);
$OutBinArr = array_reverse(str_split($OutBinStr));

// calculate
foreach($OutBinArr AS $i){
$CRCTemp = $crc[0] ^ $i;
$crc[0] = $crc[1];
$crc[1] = $crc[2];
$crc[2] = $crc[3] ^ $CRCTemp;
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5];
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $CRCTemp;
}
$crc = array_reverse($crc);
return implode('', $crc);
}

$buttonId = '00 00 14 5D 6E 0F 01';     // 59 => 3B
// $buttonId = '12 AA 12 5F 14 A2 12 12';   // 109 => 6D
$crc = bindec(createHash($buttonId));
printf("\n%d => %X",$crc,$crc);
?>
0

Другие решения

Других решений пока нет …