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