【问题标题】:How to build byte array frame and calculate checksum如何构建字节数组帧并计算校验和
【发布时间】:2017-03-15 21:08:18
【问题描述】:

我正在尝试与规范中定义的串行端口进行通信。

ser = serial.Serial("/dev/ttyUSB0", baudrate="115200")  

frame = bytearray([
    0x00, 0x00, #frame control (2 bytes)
    0x00, 0x00, #machine id (2 bytes)
    0x07, # number of bytes in data field
    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, #data field itself 
    0x00, 0x0A #checksum
])

ser.write(frame)
ser.close()

代码执行没有错误,我在单独的脚本/进程中监视相同的端口。设备应该在接收到一个成功的帧时返回一个帧。

在这个例子中,我手动计算了校验和,定义为:

双字节校验和,MSB 在前,在从 FSN.msb...DATA[dsize] 重新排列的整个帧上计算。校验和通过简单的 16 位无符号字节加法计算得到

所以在这种情况下,除了校验和之外,将帧中的所有内容相加将等于 10,如在不添加它的情况下执行 sum(frame) 所示。加上它,总和是 20。

另一端的设备可能有故障,所以这是一个很难工作的环境,但如果到目前为止有人能审查我的方法会很好吗?

生成校验和真的那么简单,还是需要其他东西?

【问题讨论】:

  • 问题到底是什么?校验和的作用是合理保证真实数据没有被篡改。因此,所有字节的简单相加就可以起到这个作用,即使它不可靠。通常校验和是有效载荷的哈希值,可能更可靠但更多需要更多计算。

标签: python binary serial-port hex checksum


【解决方案1】:

是的,就是这么简单—— 您通常会填写您的框架,并将校验和附加到另一个阶段 - 例如:

In [73]: frame = bytearray([
    ...:     0x00, 0x00, #frame control (2 bytes)
    ...:     0x00, 0x00, #machine id (2 bytes)
    ...:     0x07, # number of bytes in data field
    ...:     0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, #data field itself 
    ...:     ])


In [75]: checksum = sum(frame)

In [76]: frame.extend((checksum // 256, checksum % 256))

In [80]: print (", ".join("\\x%02X" % v for v in frame))
\x00, \x00, \x00, \x00, \x07, \x01, \x01, \x01, \x00, \x00, \x00, \x00, \x00, \x0A

现在,请注意一个细节:我以“自然顺序”添加了校验和的 2 个字节 - 首先是“MSB”(最高有效字节)。正如你的规范一样。这应该可行 - 如果不是,您可能会在其他字段之一中出现一些格式错误。

【讨论】:

  • 自 Python 3.2 以来更好的解决方案:frame.extend(sum(frame).to_bytes(2, 'big'))docs.python.org/3/library/stdtypes.html#int.to_bytes
  • 谢谢你,真的很有用。当我打印数组时,我得到了这个 bytearray(b'\x00\x00\x00\x00\x07\x01\x01\x01\x00\x00\x00\x00\x00\n') 为什么最后是 n?
  • 啊,我可以看到这是因为 print 正在将字节直接转换为字符或类似的东西? .join 是一种将它们打印为十六进制的方式。知道某些字节看起来没问题的确切原因仍然很有趣,并且随机 n 在那里?
  • 一切正常。只是 Python 中字节和字节数组的默认表示选择打印字节作为它的 ASCII 表示,如果有的话。 \n 是 ASCII“换行”字符,其数值为 10(十进制)。使用上面写的打印语句,我将序列中的所有字节显式打印为 2 位十六进制数。
  • 太棒了,我知道 10 = 换行符,但有点奇怪的是它包含一个反斜杠,因此它看起来就像它自己只是一个 n!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 2011-05-06
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多