【问题标题】:How do I decode repeating unsigned MSB and LSB 8-bit words?如何解码重复的无符号 MSB 和 LSB 8 位字?
【发布时间】:2014-05-04 11:40:34
【问题描述】:

我正在编写一个模块,该模块通过串行端口从光谱仪接收一些数据并需要对其进行解码。根据手册,频谱数据在重复无符号 MSB 和 LSB 8 位字中编码为 512 字节。我将如何在 C/C++ 中对此进行解码?

23 – 534 编码为 512 字节,重复无符号 MSB 和 LSB 8 位字 [MSB]*256 + [LSB]。

这是手册中的 sn-p。

好的,我想在这个问题中添加另一部分。根据下面的评论,这是大端的。现在,我对此感到困惑的是,如果它确实是 big-endian,那么转换为 little-endian 不会像反转所有字节的顺序一样简单吗?如果是这种情况,那么输出本质上类似于... LSB5、MSB5、LSB4、MSB4、LSB3、MSB3、LSB2、MSB2、LSB1、MSB1 等等,然后可以转换为 16位的话。我在这里有什么问题?

另外,如果这确实是大端,是否有任何本地(如果需要,甚至是特定于平台,但更快)的方法来处理转换?

【问题讨论】:

  • 这种格式不正是 16 位无符号大端序吗?
  • 我不太了解您解释的数据格式。我说的对吗?从 frame 的字节 23 到 534 有 256 个 16 位宽(= 2 字节)samples?如果是这样,那么每个样本的两个字节只有两种排列方式。LSB 在字节流中排在第一位,或者 MSB 在位。前一种情况是little-endian,后一种情况是big-endian。到目前为止,我已经理解 MSB 是第一位的,所以这会使样本大端。要在 little-endian x86 机器上解码它们,您必须 单独 对所有 256 个样本进行字节交换。
  • 至于“native”函数,如果你使用 GCC,你可以使用内置函数 uint16_t __builtin_bswap16 (uint16_t x),它不需要包含,如果你使用 Visual Studio,你可以使用unsigned short _byteswap_ushort(unsigned short val),前提是你#include <stdlib.h>
  • 对于像字节交换这样简单的事情,任何体面的编译器都可能检测移位和或实现并替换 BSWAP 指令。使用这些内置函数只会让读者和编译器更清楚,因此可能会更好地优化。
  • 字节序仅控制 samplebytes 的顺序,而不是 samplessamples 的顺序i>帧。因此,小端 16 位流类似于 [LSB0][MSB0] [LSB1][MSB1] [LSB2][MSB2] [LSB3][MSB3] [LSB4][MSB4]...,而大端 16 位流类似于 [MSB0][LSB0] [MSB1][LSB1] [MSB2][LSB2] [MSB3][LSB3] [MSB4][LSB4]...

标签: c++ c embedded


【解决方案1】:

有时我是一个过度优化者,所以即使 Fiddleing Bits 提供了一个完美的解决方案,它也有不需要的划分和不需要的分支。所以我会在这里提供一个多余的答案。

uint8_t byteArray[512];
uint16_t wordArray[256], word, byteIdx, wordIdx;

for (byteIdx=0, wordIdx=0; byteIdx < 511; )
{
    word = byteArray[byteIdx++] << 8;
    wordArray[wordIdx++] = word | byteArray[byteIdx++]
}

关键概念是将 MSB 字节向上移动 8 位(x

【讨论】:

  • 玩得好!我一直很欣赏优化。
【解决方案2】:

您需要将 MSB 和 LSB 存储到一个单词中。例如:

uint8_t msb, lsb;
uint16_t word;

word = (msb << 8) | lsb;

这样的循环看起来像这样:

uint8_t byteArray[512];
uint16_t wordArray[256], byteArrIdx;

for(byteArrIdx = 0; byteArrIdx < 512; byteArrIdx++)
{
    if((byte % 2) == 0)
        wordArray[(byteArrIdx / 2)] = byteArray[byteArrIdx] << 8;
    else
        wordArray[(byteArrIdx / 2)] |= byteArray[byteArrIdx];
}

注意:

msb &lt;&lt; 8msb * 256 的输出是相同的。我更喜欢使用位移,因为你的意图对读者来说更清楚。

【讨论】:

  • 你今天赢得了你的名字。但是你为什么不用byte &amp; 1 而不是byte % 2 呢?附言在您的代码示例中,byte 必须大于 uint8_t
  • @MarkRansom 你确定需要更大的类型吗? OP 将数据描述为 无符号 MSB 和 LSB 8 位字
  • 512 远大于 255,for 循环将永远不会终止。
  • @MarkRansom 他为什么要按位以及何时要测试每个第 n 个字节?模运算符在概念上更好。
  • 您使用byte 作为数组的索引。也许选择一个不同的名字会更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-17
  • 2021-10-28
  • 2010-10-19
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
相关资源
最近更新 更多