2011-02-25 136 views
1

有人可以解释如何用8位二进制加法来计算校验和吗?这是从文档的摘录: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

似乎对我很清楚。你不明白什么? – 2011-02-25 10:24:47

+0

你能告诉我一个例子(示例代码)吗?从来没有做过这样的事情...... – ekstrakt 2011-02-25 10:34:35

+0

而你在Delphi或Java中需要它吗? – 2011-02-25 11:14:22

回答

4

将每个字符视为整数值。由于每个字符的高位是,假设为零(因为在规范中并没有说你需要检查它),所以用它来掩盖它的值(伪C/C++/Java/whatever):

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位,而使用截断在校验和的使用点。但是,这不会为您节省很多性能,但是 - 您的I/O将会更加昂贵 - 并且会导致您在重构代码后的某个日后忘记执行此操作的可能性。

0

这个(未经测试的)类似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; 
} 

+0

我认为OP正在寻找8位校验和,而不是7位校验和。 – 2011-02-25 12:09:36

0

在Java中,您可以执行以下操作。

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

OutputStream os = 
os.write(total); 
4

另外,请使用以下功能。

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,没有“对”:

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声明为字节,所以它会“忽略”携带超出了第8位。您可以传递所有要添加的字节。

使用SysUtils的函数IntToHex将8位结果转换为两个可打印的ASCII十六进制字符。

例如:ChkSum := IntToHex(Summatory(Data), 2);

+0

用于Delphi示例代码的+1 - 您应该已经使用(const Data:AnsiString)作为参数,但其余都是OK。对于旧版本的Delphi,没有“in”,你应该添加一个I局部变量,然后对于i:= 1到length(Data)做结果:= result + ord(Data [i]); – 2011-02-25 14:43:37

+0

谢谢@ A.Bouchez。我在回答中提出了你的建议。 – 2011-02-25 14:49:59