解码财务打印机的自定义CRC算法

时间:2016-04-22 09:38:31

标签: php algorithm binary bit-manipulation crc

我在这里碰到了一堵砖墙,我需要你的帮助。我有一台财务打印机(Datecs DP-50)可以集成到销售的Chrome扩展应用程序上。问题是我们无法使用驱动程序,因为应用程序将在远程服务器上运行,而不是在运营商设备上运行,我们必须以原始方式发送数据。 该应用程序使用Laravel 5.1作为额外信息在PHP中编码。

所以我有一个带有自定义多项式x ^ 15 + 1的CRC基数16,但它比这更多,我无法弄明白。我将粘贴在手册中的文档下面。

   The two CRC bytes are calculated according to the formula x^15 + 1. In the 
    calculation are included all data bytes plus the byte for block end. Every byte passes 
    through the calculation register from teh MSB to LSB.
    Three working bytes are used - S1, S0 and TR
    S1 - Most significant byte from the CRC ( it is transmitted immediatelly after END)
    S0 - Least significant byte from the CRC ( It is transmitted after S1)
    TR - the current transmitted byte in the block.

    The CRC is calculated as follows:
    1. S1 and S0 are zeroed
    2. TR is loaded with the current transmitted byte. The byte is transmitted.
    3. Points 3.1 and 3.2 are executed 8 times:
    3.1. S1, S0 and TR are shifted one bit to the left.
    3.2. If the carry bit from S1 is 1, the MSB of S1 and LSB of S0 are inverted.
    Points 2 and 3 are executed for all bytes, included in the calculation of the CRC - from 
    the first byte after BEG up to and including byte END.
    4. TR is loaded with 0 and point 3 is executed
    5. TR is loaded with 0 and point 3 is executed
    6. Byte S1 is transmitted
    7. Byte S0 is transmitted

例如,“A”字符串的CRC(仅S1和S0)为十六进制:fe 09。对于“B”=> fc 09,对于“C”=> 7d f6。对于“A”,完整的CRC将是0d fe 09。 串行COM监视器中的TR似乎是一个常量,始终表示为0d十六进制。

任何帮助解码这一点是值得赞赏的。 提前谢谢!

1 个答案:

答案 0 :(得分:1)

除了拼写错误之外,描述是有缺陷的,因为它错过了S1,S0,TR寄存器按顺序在左移时被视为单个24位寄存器的关键细节。如果你这样做,那么你得到你引用的结果。您需要在计算中包含0x0d(“END”字节)。

function crc16($crc, $byte) {
    $crc = ($crc << 8) + $byte;
    for ($k = 0; $k < 8; $k++)
        $crc = ($crc & 0x800000) == 0 ? $crc << 1 : ($crc << 1) ^ 0x800100;
    $crc = ($crc >> 8) & 0xffff;
    return $crc;
}

$crc = 0;
$crc = crc16($crc, ord("A"));
$crc = crc16($crc, 13);
$crc = crc16($crc, 0);
$crc = crc16($crc, 0);
echo dechex($crc);

给出fe09