8-битное двоичное сложение - PullRequest
2 голосов
/ 25 февраля 2011

Может кто-нибудь объяснить, как вычислить контрольную сумму с 8-битным двоичным сложением? Это выдержка из документации:

Это общая форма сообщений:

STX | TYPE | FS | DATA | FS | CHK | ETX

STX - HEX 02

ETX - HEX 03

FS - HEX 15

«Тип» - это уникальный 1-байтовый идентификатор сообщения (например, «P» для сообщения опроса). «Данные» содержат печатные символы ASCII.

Контрольная сумма

Контрольная сумма вычисляется для всех символов, включая все символы <FS>, от <STX> до <CHK>. Контрольная сумма вычисляется с помощью 8-разрядного двоичного сложения всех включенных символов с 8-м битом или битом четности, предполагаемым равным нулю. Переносится после 8-го бита. 8-битный результат преобразуется в два печатных шестнадцатеричных символа ASCII в диапазоне от 00 до FF, которые затем вставляются в поток данных как <CHK>. Шестнадцатеричные символы A-F прописные. Принимающее устройство пересчитывает контрольную сумму в буферизованном сообщении и сравнивает ее с полученной контрольной суммой. Сравнение является основой для последующего подтверждения (<ACK>) или отрицательного подтверждения (<NAK>) передачи.

Ответы [ 4 ]

5 голосов
/ 25 февраля 2011

Рассматривать каждый символ как целочисленное значение. Поскольку старший бит каждого символа равен , предполагается, что равен нулю (поскольку в спецификации не сказано, что вам нужно его проверять), замаскируйте его значение чем-то вроде этого (псевдо-C / C ++ / Java / что угодно) :

get_next_character() & 0x7f;

Теперь вы просто добавляете (псевдо-C / C ++ / Java / что угодно):

int s = 0;
while(!end_of_string())
{
    s += get_next_character() & 0x7f;
    s &= 0xff;
}

Это последовательно добавит каждый символ ASCII и удалит все, что за 8-м битом, из полученной суммы. Когда вы все закончите (C или плохо написанный C ++):

printf("Checksum: %02x\n", s);  /* You may need %02X for uppercase.
                                   I don't remember my printf codes anymore. */

В качестве оптимизации (если она вам действительно нужна - вряд ли в этом случае!) Вы можете отложить бит s &= 0xff и вместо этого использовать усечение в точке использования контрольной суммы. Однако это не сильно сэкономит на производительности - ваш ввод-вывод будет намного дороже - и вы можете забыть сделать это позже, когда вы будете реорганизовывать свой код.

4 голосов
/ 25 февраля 2011

Для этого используйте следующую функцию.

function Summatory(const Data: AnsiString): Byte;
var
    C: AnsiChar;
begin
    Result := 0;

    for C in Data do
    begin
        Result := Result + Ord(C);
    end;
end;

Для более старых версий Delphi без «for in»:

function Summatory(const Data: AnsiString): Byte;
var
    I: Integer;        
begin
    Result := 0;

    for I := 1 to Length(Data) do
    begin
        Result := Result + Ord(Data[I]);
    end;
end;

Функция Summatory объявлена ​​как Byte, поэтому она «игнорирует» переносы после 8-го бита,Вы можете передать все байты, которые хотите добавить.

Используйте функцию IntToHex из SysUtils, чтобы преобразовать 8-битный результат в два печатных шестнадцатеричных символа ASCII.

Ex: ChkSum := IntToHex(Summatory(Data), 2);

0 голосов
/ 25 февраля 2011

В Java вы можете сделать следующее.

byte[] bytes =
byte total = 0;
for(byte b: bytes) total += b;

OutputStream os = 
os.write(total);
0 голосов
/ 25 февраля 2011

Решает ли эта (непроверенная) JavaScript-подобная функция вашу проблему? function calc_checksum( DATA ) { var i; var checksum = 0; for ( i = 0; i < DATA.length; ++i ) { checksum += DATA[i]; // any carry just falls off the high-order end } return 0x7F & checksum; }

...