【问题标题】:bit-shift operation in accelerometer code加速度计代码中的位移位操作
【发布时间】:2017-03-21 03:44:46
【问题描述】:

我正在对我的 Arduino 微控制器进行编程,并且我找到了一些用于接受加速度计传感器数据以供以后使用的代码。我可以理解除以下代码之外的所有内容。我想对正在发生的事情有一些直觉,但是经过所有的搜索和阅读,我无法完全理解正在发生的事情并真正理解。

我上过一门 C++ 课程,但我们在按位运算或位移位或任何您喜欢的名称方面做得很少。让我试着解释一下我认为我理解的内容,您可以在需要的地方纠正我。

所以:

  1. 我认为我们在 x 中存储了一个值,事实上非常确定。
  2. 似乎数组“buff”中的数据,插槽号 1,被设置为整数数据类型。
  3. 槽 1 中的值被向左移动了 8 位。(这是否指向 buff 槽 0?)

这个新值正在与 buff slot 0 中的数据进行比较,如果任一位为真,则存储在 x 中的数据中的位也将为真,因此,0 和 1 = 1,0 和 0 = 0 和 1最后存储的值是0 = 1。

代码对所有三个轴执行此操作:x、y、z,但我不确定为什么...我需要帮助。在我进步之前,我希望完全理解。

//each axis reading comes in 10 bit resolution, ie 2 bytes.  
// Least Significant Byte first!!
//thus we are converting both bytes in to one int
x = (((int)buff[1]) << 8) | buff[0];   
y = (((int)buff[3]) << 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];

【问题讨论】:

    标签: arduino bit-manipulation accelerometer microcontroller bit-shift


    【解决方案1】:

    此代码用于将原始加速度计数据(6 字节数组)转换为三个 10 位整数值。正如评论所说,数据首先是 LSB。那就是:

    buff[0] // least significant 8 bits of x data
    buff[1] // most significant 2 bits of x data 
    buff[2] // least significant 8 bits of y data
    buff[3] // most significant 2 bits of y data 
    buff[4] // least significant 8 bits of z data
    buff[5] // most significant 2 bits of z data 
    

    它使用按位运算符将两个部分放在一个变量中。 (int) 类型转换是不必要的并且(恕我直言)令人困惑。这个简化的表达式:

    x = (buff[1] << 8) | buff[0];
    

    获取buff[1] 中的数据,并将其左移8 位,然后将buff[0] 中的8 位放入如此创建的空间中。例如,让我们将这 10 位标记为 aj

    buff[0] = cdefghij
    buff[1] = 000000ab
    

    然后:

    buff[1] << 8 = ab00000000
    

    还有:

    buff[1] << 8 | buff[0] = abcdefghij
    

    【讨论】:

    • 谢谢!我花了几天时间阅读这些东西,你和社区的其他人在不到 15 分钟的时间内给我带来了我的灵感时刻!您的分步说明使您更容易理解!
    • 传入的数据(buff)也是二进制补码,看起来Arduino微处理器在将位分配给xyz时会保持符号,这是我的浮点数版本。这很混乱。
    • @mrmagooey,你为什么不想保留这个标志?
    • 对不起,我应该更清楚一点,我确实想要这个标志,并且发生的操作是想要的,只是上面代码的另一部分让我感到困惑。
    【解决方案2】:

    槽 1 中的值被向左移动了 8 位。(这是否指向 buff 槽 0?)

    不。位运算符不是指针运算,不要混淆两者。向左移动 N 位(大致)相当于乘以 2 的 Nth 次方(C 中的一些极端情况除外,但我们先不谈这些)。

    这个新值正在与 buff slot 0 中的数据进行比较,如果任一位为真,则存储在 x 中的数据中的位也将为真

    没有。 | 不是逻辑 OR 运算符(即 ||),而是按位 OR 运算符。代码所做的只是将buff[0]buff[1] 中的两个字节组合成一个2 字节整数,其中buff[1] 表示数字的MSB。

    【讨论】:

    • 非常感谢!我们可以再深入一点吗?这些位实际上是如何组合的?如果我们取 buff N 中的值并移动 8 以及你所说的,乘以 2 的 8 次方,它是如何组合的?如果我可能猜到……我们是从 16 位或 2 个字节开始,然后将前 8 位中的数据向左移动,并用 buff 槽中的数据替换移位输入的零0?另外,你能解释一下MSB吗?我知道它代表最重要的字节,但这是我的知识范围。提前谢谢!
    • @user2701295 乍一看,您的猜测似乎是正确的。最高有效字节:在数字中具有最大“权重”(对值有贡献)的字节。
    • 所以如果我们不关心准确性,我们可以扔掉 LSB 吗?就像如果我们有一个数以千万计的数字,我们就不会真正关心数百位是什么?是这个主意吗?
    • @user2701295 不。这种转变总是需要的。拿起纸和笔去解决它,你会明白为什么。
    【解决方案3】:

    设备结果为6个字节,字节需要重新排列成3个整数(具有最多只能占用10位的值)。

    所以前两个字节如下所示:

    00: xxxx xxxx <- binary value
    01: ???? ??xx
    

    ???部分不是结果的一部分,因为 xxx 部分包含 10 位。我猜硬件的构建方式是 ???部分全为零。

    要将其转换为单个整数变量,我们需要所有 8 个低位加上高 2 位,左移 8 个位置,这样它们就不会干扰低 8 位。逻辑 OR(| - 竖线)会将这两个部分连接成一个整数,如下所示:

    x: ???? ??xx xxxx xxxx <- binary value of a single 16 bit integer
    

    实际上,'int' 有多大(以位为单位)并不重要,因为在这种情况下,剩余的位(超过 16 位)将为零。

    【讨论】:

      【解决方案4】:

      扩展和澄清 Carl Norum 的回复。

      需要 (int) 类型转换,因为源是一个字节。在将结果保存到 X 之前对源数据类型执行位移。因此,必须将其转换为至少 16 位(一个 int)才能位移 8 位并在执行 OR 操作和结果之前保留所有数据已保存。

      代码没有告诉你的是这是否应该是一个无符号整数或位数据中是否有符号。我希望加速度计可以提供 -ve 数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-08
        • 1970-01-01
        • 2022-11-17
        • 1970-01-01
        • 2011-05-02
        相关资源
        最近更新 更多