【问题标题】:Converting raw Accelerometer values to 12 bit number将原始加速度计值转换为 12 位数字
【发布时间】:2018-01-18 04:43:43
【问题描述】:

我正在编写一个内置于微控制器(TZ1000 系列)中的加速度计。我正在尝试将数据 BLE 发送到 PC 应用程序。我必须以 2 个字节发送数字并在应用程序端接收它并将其组合成一个 12 位数字。我在将实际的原始加速度计值转换为 12 位数时遇到问题。我正在阅读以下格式。

acc->ReadAcceleration((uint16_t*)buf);  
ChannelX[M] = (buf[0].acceleration << 4) & 0xFFF0;
ChannelY[M] = (buf[1].acceleration << 4) & 0xFFF0;
ChannelZ[M] = (buf[2].acceleration << 4) & 0xFFF0;

其中变量的类型和大小如下,

int16_t ChannelX[4] = {0,0,0,0};
int16_t ChannelY[4] = {0,0,0,0};
int16_t ChannelZ[4] = {0,0,0,0};

buf的类型为static ACCEL_ACCELERATION buf[12];,其结构如下,

  typedef struct _ACCEL_ACCELERATION {
       uint16_t updated      : 1;
      uint16_t reserved     : 3;
      int16_t  acceleration :12;
    } ACCEL_ACCELERATION;

现在,当我将此数据转换为两个字节并通过 BLE 传输时,我遵循以下逻辑。

uart_tx_data[i]   = (uint8_t) (ChannelX[j] & 0xFF);
uart_tx_data[i+1] = (uint8_t) ((ChannelX[j]>>12) & 0x0F) ;

uart_tx_data[i+2] = (uint8_t) (ChannelY[j] & 0xFF);
uart_tx_data[i+3] = (uint8_t) ((ChannelY[j]>>12) & 0x0F) ;

uart_tx_data[i+4] = (uint8_t) (ChannelZ[j] & 0xFF);
uart_tx_data[i+5] = (uint8_t) ((ChannelZ[j]>>12) & 0x0F) ;

其中变量的类型为static uint8_t uart_tx_data[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

在接收端,我将其转换为 12 位数字,如下所示,

X[i]= (num[2] & 0xFF) | ((num[3] & 0x0F) << 12);

在哪里int[] X= new int[2];

我得到的值是错误的,我通过在加速度计上进行 1g 测试来检查它。例如,当它变平时,它应该给出一个接近零的数字。在 1g 时,它应该根据我设置的灵敏度给出一个数字(在我的情况下它是 8G,值为 256)。

我使用的逻辑有什么问题吗?我请求有人帮助我解决这个问题。

提前谢谢你。

【问题讨论】:

  • 不确定这有多大帮助,但您可能希望确保以相同的字节顺序发送和接收值。
  • 说出缓冲区内的数字uart_tx_data[2] = 0x20uart_tx_data[3]=0x01。我想要的输出应该是X[i]=0x0120,它是一个 12 位数字。
  • 你的轮班似乎不合理。您正在发送最低八位和最高四位,而您正在移动所有内容,因此最低四位是空的。在我看来,您似乎缺少了四位结果,而最低四位始终为零。
  • 这里有很多字节洗牌,我很难跟踪它,这将是我的第一个猜测问题。有什么方法可以打印出来并查看每一步的结果(来自加速度计的原始数据、通道中的数据、uart_tx_data 中的数据)?此外,除非您确定位域运行正常,否则请阅读这些内容。有一些与位域相关的“陷阱”,我认为归结为它们是实现定义的。它们生成的代码看起来很优雅,但我相信移位和位掩码更健壮。
  • @yano 我纠正了它,在uart_tx_data 缓冲区中应该是 8 位右移而不是 12 位。谢谢。

标签: c byte microcontroller accelerometer bit-shift


【解决方案1】:

你的班次都结束了。使用常量来查看发生了什么。示例:将 0x1234 放入结构中(注意我假设是 16 位变量,而不关心结构中的位字段会稍微改变一些东西,但不是它不起作用的原因)

ChannelX[M] = (buf[0].acceleration << 4) & 0xFFF0;

这将导致 0x2340。不知道为什么你想要最低四位为零,但让我们继续吧。然后你发送它:

uart_tx_data[i]   = (uint8_t) (ChannelX[j] & 0xFF);
uart_tx_data[i+1] = (uint8_t) ((ChannelX[j]>>12) & 0x0F) ;

第一部分是0x2340 &amp; 0xff == 0x40,所以你总是从最低位发送四个零。第二部分将是0x2340 &gt;&gt; 12 == 0x02,所以你错过了整个 3 部分。

为什么不简单地取acceleration 的值并发送它而不使四个最低位为零?位字段将使其成为 12 位值。当发送 8,而不是 12 时。

ChannelX[M] = buf[0].acceleration;
uart_tx_data[i]   = (uint8_t) (ChannelX[j] & 0xFF);
uart_tx_data[i+1] = (uint8_t) ((ChannelX[j]>>8) & 0x0F);

【讨论】:

  • 感谢您的回复。是的,我将它从 12 更正为 8,它正在发送正确的值。对接收方的任何想法X[i]= (num[2] &amp; 0xFF) | ((num[3] &amp; 0x0F) &lt;&lt; 8); 说我得到的值不是 256,而是 128。我在接收方使用处理 IDE。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多