【问题标题】:Efficient way to create/unpack large bitfields in C?在 C 中创建/解压缩大型位域的有效方法?
【发布时间】:2010-04-05 01:35:02
【问题描述】:

我有一个微控制器从许多 ADC 中采样,并以非常低的比特率通过无线电发送测量结果,带宽正在成为一个问题。

现在,每个 ADC 只给我们 10 位数据,并且它被存储在一个 16 位整数中。有没有一种简单的方法可以确定性地打包它们,以便第一次测量在第 0 位,第二次在第 10 位,第三次在第 20 位,等等?

更糟糕的是,微控制器是小端的,我无法控制另一端计算机的端序。

编辑:到目前为止,我最喜欢@MSN 的回答,但我会回复 cmets

@EvilTeach:我不确定确切的位模式是否会有所帮助,或者如何最好地仅使用文本进行格式化,但我会考虑一下。

@Jonathan Leffler:理想情况下,我会将 8 个 10 位值打包成 10 个 8 位字节。如果它使处理更容易,我会满足于 4 个字节中的 3 个值或 8 个字节中的 6 个值(尽管 2 与我等价,相同数量的“浪费”位)

【问题讨论】:

  • 我认为这会有所帮助,显示您的传入位模式的图表以及所需的结果。
  • 'Bit fields' 和 'Portability' 很少以正面的方式出现在同一个句子中;位字段不可移植。您是想将 3 x 10 位值打包成一个 32 位整数,还是将 6 x 10 位值打包成一个 64 位整数,还是想在更长的内存范围内保持连续?

标签: c portability bitmask


【解决方案1】:

使用位 0 和 31 来确定字节顺序并在中间打包 3 个 10 位值。测试匹配字节序的一种简单方法是将位 0 ​​设置为 0,将位 31 设置为 1。在接收端,如果位 0 为 1,则断言位 31 为 0 并交换字节序。否则,如果位 0 为 0,则断言位 31 为 1 并提取 3 个值。

【讨论】:

    【解决方案2】:

    您可以使用位域,但未定义机器字内的顺序:

    也就是说,它看起来像:

    struct adc_data { 
    unsigned first :10;
    unsigned second :10; 
    unsigned third :10; 
    };
    

    编辑:已更正,感谢 Jonathan。

    【讨论】:

    • 肯定会更像'struct { unsigned first :10; unsigned second :10; unsigned third :10; } adc_data;'?您不希望分配 1 位和未分配 9 位;你想要分配三组 10 位,不是吗 - 或者提问者不是。
    【解决方案3】:

    对于字节序,最简单的做法是简单地选择一个用于传输。要打包传输流中的位,请使用累加器(在您的情况下至少为 17 位),在其中一次移入 10 位并跟踪其中有多少位。当您传输一个字节时,您从累加器中取出一个字节,从计数中减去 8,然后将累加器移位 8。我在这里松散地使用“传输”,您可能存储到缓冲区中以供以后传输。

    例如,如果传输是小端序,则在累加器顶部(在其 MS 位中)移入 10 位,并从底部拉出字节。例如:对于两个值 a 和 b:

    Accumulator     Count
    (MS to LS bit)   
    aaaaaaaaaa      10      After storing a
    aa              2       After sending first byte
    bbbbbbbbbbaa    12      After storing b
    bbbb            4       After sending second byte
    

    接收是一个类似的拆包操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      相关资源
      最近更新 更多