Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Системное программирование > Алоритм калькуляции чексумы


Автор: tuneil 16.11.2011, 20:14
Приветствую.
Есть некий алгоритм калькуляции CRC сообщения, с которым никак немогу разобратся и потому вынужден просить помощи более опытных товарищей.
Сам алгоритм:

ALGORITHM FOR CRC CALCULATION

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


Формат передаваемого сообщения: 

- control character for beginning of a block BEG ( 0A HEX or ^J)
- data bytes
- control symbol for end of block END ( 0D HEX or ^M)
- 2 control bytes CRC.

Вот часть реализованого мною алгоритма:
 
Код

@read_table = qw(R 2 ; 2 ;);
# CRC calculation
###############################
$length = $#read_table + 1;
$S1=0;
$S0=0;
for ($i=0; $i<$length; $i++) {
    $TR = unpack("H*", $read_table[$i]);
    $Result1 = $S1 ^ $TR;
    $msb = $Result1 & 0x80;
    if ($msb == 1) {
        $S1 << 1;
        $S0 << 1;
    } else   {
        $Result1 = hex($Result1);
        for ($j=0; $j<8; $j++ )   {
            $Result1 = $Result1 << 1;
            }
        }
}


Проблема состоит в том, что после сдвига на 1 бит, с каждой последующей итерайцией значение S1 превышает 1 байт, и становится невозможным подсчитать чексуму.
Это мой первый скрипт, если упустил какие-то базовые понятия - буду признателен за советы.

Автор: tishaishii 10.1.2012, 00:01
А hex(x) << 1 зачем?
S1 и S0 не понятно какие значения принимают.
Как-то алгоритм разваливается.
http://search.cpan.org/search?query=CRC&mode=module
Digest::CRC

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)