4

我有关于创建这样描述的消息校验和的说明:

校验和由一个字节组成,该字节等于从“消息类型”字开始到消息块末尾的所有字节的二进制补码和(不包括传输的校验和)。最高有效位的进位被忽略。

我发现的另一个描述是:校验和值包含数据消息中其他字(即消息类型、消息长度和数据字)的模 256 和的二进制补码。接收设备可以计算接收到的字的模256和并将这个和加到接收到的校验和字上。结果为零通常表示消息已正确接收。

我理解这意味着我将消息中所有字节的值(不包括校验和)相加,得到这个数字的模 256。得到这个数字的二进制补码,这就是我的校验和。

但是我在使用示例消息示例时遇到了问题(来自设计文档,因此我必须假设它已正确编码)。

unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};

所以最后一个字节 0xE 是校验和。我计算校验和的代码如下:

bool isMsgValid(unsigned char arr[], int len) {
   int sum = 0;
   for(int i = 0; i < (len-1); ++i) {
      sum += arr[i];
   }
   //modulo 256 sum
   sum %= 256;

   char ch = sum;

   //twos complement
   unsigned char twoscompl = ~ch + 1;

   return arr[len-1] == twoscompl;
}


int main(int argc, char* argv[])
{
   unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};
   int arrsize = sizeof(arr) / sizeof(arr[0]);

   bool ret = isMsgValid(arr, arrsize);

   return 0;
}

规格在这里:= http://www.sinet.bt.com/227v3p5.pdf

我假设我误解了所需的算法。知道如何创建这个校验和吗?

Flippin 规范编写者在他们的数据示例中犯了一个错误。刚发现这个然后回到这里发现其他人也发现了。对不起,如果我浪费了你的时间。我将研究回复,因为它看起来像是一些有助于改进我的代码的有用评论。

4

3 回答 3

6

您从链接的 pdf 中错误地复制了示例消息。第二个参数长度为 9 个字节,但您在代码中使用了 0x08。

当参数中确实有 9 个字节时,该文档在第三列中错误地声明了“8 个字节”。第二列正确地指出“00001001”。

换句话说,您的测试信息应该是:

{0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30, // param1
 0x2,0x9,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe}  // param2
     ^^^

ret == true当我尝试您的程序时,使用正确的消息数组。

于 2012-09-02T18:56:46.953 回答
1

同意评论:看起来校验和是错误的。这些数据在 .PDF 中的什么位置?

一些一般提示:

使用无符号类型作为累加器;这为您提供了明确定义的溢出行为,并且您需要更长的消息。同样,如果将结果存储在 char 变量中,请将其设为 unsigned char。

但是您不需要存储它;只需使用无符号类型进行数学运算,对结果进行补码,加 1,并屏蔽高位,以便获得 8 位结果。

另外,这里有一个技巧,如果您使用的是使用二进制补码算法的硬件:只需添加所有值,包括校验和,然后屏蔽高位;如果输入正确,结果将为 0。

于 2012-09-02T18:49:07.377 回答
1

接收设备可以计算接收到的字的模256和并将这个和加到接收到的校验和字上。

使用此条件来理解校验和要容易得多:

{byte 0} + {byte 1} + ... + {last byte} + {checksum} = 0    mod 256
{checksum} = -( {byte 0} + {byte 1} + ... + {last byte} )   mod 256

正如其他人所说,在处理单个位时,您确实应该使用无符号类型。在进行模运算时也是如此。如果你使用有符号类型,你会让自己面临大量与符号相关的错误。OTOH,几乎你打开自己使用无符号数字的唯一错误就是忘记2u-3u是一个正数。

(请注意将有符号和无符号数字混合在一起:其中也涉及很多微妙之处)

于 2012-09-02T18:59:50.153 回答