【问题标题】:How to convert a large integer to bytes如何将大整数转换为字节
【发布时间】:2016-02-06 15:29:20
【问题描述】:

我需要通过串行通信将值 115200 作为参数发送到外部设备,该设备需要将参数作为字节数组的一部分,格式为:0x00, 0x00, 0x00, 0x00,但我不知道如何转换它成那种格式。 我在 Processing 中执行此操作,因此 Processing/java 解决方案将来会派上用场,但 ATM 如果我可以发送带有此特定变量的消息,我将非常高兴。

这是字节数组:

byte[] tx_cmd = { 0x55, -86,             // packet header (-86 == 0xAA) 
                0x01, 0x00,              // device ID
                0x00, 0x00, 0x00, 0x00,  // input parameter NEEDS TO BE 115200
                0x04, 0x00,              // command code
                0x00, 0x01 };            // checksum

参数需要放在第5到第8位(byte[4] - byte[7])。

消息格式为little endian 这是消息结构:

0 0x55 BYTE 命令起始码1

1 0xAA BYTE 命令起始码2

2 Device ID WORD 设备ID:默认为0x0001,始终固定

4 参数 DWORD 输入参数

8 命令字 命令码

10 校验和 WORD 校验和(字节加法) OFFSET[0]+…+OFFSET[9]=校验和

任何建议将不胜感激。 谢谢

【问题讨论】:

  • 您的问题是如何将 int 转换为 sizeof(int) 大小的字节数组?或者是 115200 的值?
  • 明确说明预期的字节序 - 115200 的最低或最高有效字节是否进入字节 [4]? (消息显示为小端)。你知道如何计算校验和吗?如果没有,使用什么算法以及它是如何应用在这里的?也许这个协议/格式有名字??
  • @HannesAndersson :你说过你控制的设备是小端的。现在的问题是 - 进行控制的设备的字节序是什么?如果它显然是大端,你必须交换字节(如提供的解决方案所示)如果进行控制的设备是小端架构,并且被控制的设备需要小端值,那么你不必做字节交换。
  • 请在交叉帖子之间链接:forum.processing.org/two/discussion/13411/…

标签: java c type-conversion bytearray processing


【解决方案1】:

你尝试打包一个int成字节,你没有提到它是否是网络命令,所以我们假设它是(例如第一个字节,tx_cmd[4],是最高的字节数):

unsigned int baudrate = 115200;
tx_cmd[4] = (baudrate >> 24) & 0xff;
tx_cmd[5] = (baudrate >> 16) & 0xff;
tx_cmd[6] = (baudrate >> 8) & 0xff;
tx_cmd[7] = baudrate & 0xff;

一般来说,拥有像int_to_bytes 和类似的函数非常方便,它们以通用的方式执行此操作并减少代码混乱。

【讨论】:

  • 感谢您的回答!虽然我没有让它工作,因为这导致:[4] 0 [5] 1 [6] 194 [7] 0 所以 [6] 仍然很大,知道我做错了什么吗?
  • 194 不算大——为什么这么说?
  • @HannesAndersson 0, 1, 194, 0(十进制)是 0x00, 0x01, 0xC2, 0x00(十六进制),即 0x0001C200 = 115200 十进制。显然它现在是大端形式。对我来说似乎是正确的。
【解决方案2】:

建议创建一个函数来打包所有东西

#define byte_n(x, b) ((x >> (b*8)) & 0xFF)

void CreatePacket(byte tx_cmd[], uint16_t device_id, uint32_t param, uint16_t command) {
  #define HEADER 0xAA55
  tx_cmd[0] = byte_n(HEADER, 0);
  tx_cmd[1] = byte_n(HEADER, 1);
  tx_cmd[2] = byte_n(device_id, 0);
  tx_cmd[3] = byte_n(device_id, 1);
  tx_cmd[4] = byte_n(param, 0);
  tx_cmd[5] = byte_n(param, 1);
  tx_cmd[6] = byte_n(param, 2);
  tx_cmd[7] = byte_n(param, 3);
  tx_cmd[8] = byte_n(command, 0);
  tx_cmd[9] = byte_n(command, 1);
  unsigned checksum = 0;
  for (int i=0; i<10; i++) {
    checksum += tx_cmd[i];
  }
  tx_cmd[10] = byte_n(checksum, 0);
  tx_cmd[11] = byte_n(checksum, 1);
}

byte tx_cmd[12];
device_id = 1;
baud = 115200;
command = 4;
CreatePacket(tx_cmd, device_id,  baud, command);

【讨论】:

  • 非常感谢!这确实很方便!
【解决方案3】:

你需要屏蔽和移位

int num = 115200
int b1 = (num & 0xff000000) >> 24
int b2 = (num & 0x00ff0000) >> 16
int b3 = (num & 0x0000ff00) >> 8
int b4 = (num & 0x000000ff) >> 0

【讨论】:

  • 这是一个有符号整数,移动它们会产生奇怪的结果。最好使用无符号。
  • 感谢您的回答,但它会引发错误:The operator &amp;&amp; is undefined for the argument type(s) int, int 知道我做错了什么吗?
  • 哎呀-我的错-应该是&
【解决方案4】:

由于字节应为小端格式,您可以按如下方式设置它们:

uint32_t value = 115200;
tx_cmd[4] = value & 0xff;
tx_cmd[5] = (value >> 8) & 0xff;
tx_cmd[6] = (value >> 16) & 0xff;
tx_cmd[7] = (value >> 24) & 0xff;

您使用的值是无符号的,这一点很重要,否则如果设置了最高有效位,您就有可能将 1 移入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 1970-01-01
    • 2013-07-23
    • 2019-09-21
    • 2023-03-09
    • 2012-09-01
    相关资源
    最近更新 更多