基于ICD描述的卫星数据帧16位校验和算法实现疑问
基于ICD描述的卫星数据帧16位校验和算法实现疑问
看起来你对ICD里的校验和描述理解出现了关键偏差,咱们一步步拆解问题,帮你修正代码:
首先明确ICD的核心要求:
Binary 16-bit sum of data words (2 bytes sum, first byte is MSB), ignoring carry.
翻译过来的关键信息是:
- 这是16位二进制加法和(sum),不是你代码里用的异或(xor)——这是最核心的错误点
- 数据按2字节为一个数据字处理,每个字的第一个字节是高位(MSB),也就是每个数据字的数值是
(第1字节 << 8) + 第2字节 - 忽略进位:每次累加后,只保留结果的低16位,超过16位的进位直接丢弃(比如累加后结果是0x10001,就只保留0x0001)
你的代码用了异或运算,这属于另一种校验逻辑(异或校验),和ICD要求的“和校验”完全不是一回事,这也是你不确定正确性的根本原因。
修正后的Pascal实现
根据ICD要求,我们可以写出正确的校验和计算函数:
function T_Appli.checksum_calc(tab: array of byte; length: cardinal): word; var checksum : word; i : cardinal; data_word : word; begin checksum := 0; // 遍历数据部分(排除最后2字节的校验和),每次处理2字节的数据字 i := 0; while i < length - 2 do begin // 按MSB在前的规则组成16位数据字 data_word := (tab[i] shl 8) or tab[i+1]; // 累加,word类型会自动截断超过16位的部分(忽略进位) checksum := checksum + data_word; i := i + 2; end; // 处理数据部分长度为奇数的情况(如果ICD允许的话) // 如果数据部分最后剩1个字节,按高8位补0的方式作为16位字累加 if i = length - 2 then begin data_word := tab[i]; // 等价于 (0 shl 8) or tab[i] checksum := checksum + data_word; end; Result := checksum; end;
关键细节说明
- 加法而非异或:严格遵循ICD里的“sum”要求,用加法替代异或运算
- 数据字的组成:确保第一个字节是MSB,也就是把第一个字节左移8位作为高8位,第二个字节作为低8位
- 忽略进位:Pascal的
word类型是16位无符号整数,当累加结果超过16位时会自动溢出截断,正好符合“忽略进位”的要求(如果要更明确,也可以写成checksum := (checksum + data_word) and $FFFF;) - 奇数长度处理:如果数据部分(排除校验和)的长度是奇数,最后剩下的单个字节按高8位为0的16位字处理——如果ICD明确要求数据部分必须是偶数字节,这部分可以去掉,否则保留兼容逻辑
测试示例
举个简单例子验证:
假设数据帧(不含校验和)是[0x01, 0x02, 0x03, 0x04],数据字是0x0102和0x0304,累加和为0x0102 + 0x0304 = 0x0406,最终校验和就是0x0406,和我们的代码计算结果一致。
备注:内容来源于stack exchange,提问作者DexTr
相关产品推荐
相关产品推荐

