[英]8bit (two values) array to 16bit array (one value)
我正在从传感器读取数据,该传感器将它们作为两个8位值发送,并且用户必须将它们转换为一个带符号的16位值。 我将这些值保存到一个5400个元素的数组中(传感器是加速度计+陀螺仪+磁力计,所以是9个轴,所以最后每个轴都有300个值)。 所以可以说我需要从加速度计的X轴读取数据。 在我的数组中,我将它们保存在前两个位置,所以我的accX读数分别位于索引0,1,然后是18,19,然后是36,37,依此类推.....现在,我需要将它们提取到具有300个元素的新16bit数组中只能代表加速度计的X轴。 我想到的是:
uint8_t rawData[5400]={0};
int16_t *AccX = malloc(300*sizeof(int16_t));
for(int i=0;i<300;i++){
AccX[i]=(rawData[i+1+i*17]<<8 | rawData[i+0+i*17]);
}
//do some calculations
free(AccX);
但是在我的AccX数组中有一些我不希望出现的值。 知道可能出了什么问题吗? 传感器为LSM9DS1。
编辑:对不起,我没有提供有关该设备的更多信息。 我肯定知道这可行:
x_accel = (rawData[1]<<8 | rawData[0]);
我还检查了rawData数组,它包含正确的数据。 当我尝试将数据填充到AccX数组时出错
查看数据表 。 本质上,一个封装中有两个独立的设备。
您需要加速度计/陀螺仪设备寄存器:
温度的21和22(0x15和0x16)
陀螺仪X轴的24和25(0x18和0x19)
用于陀螺仪Y轴的26和27(0x1A和0x1B)
陀螺仪Z轴的28和29(0x1C和0x1D)
加速度计X轴的40和41(0x28和0x29)
加速度计X轴的42和43(0x2A和0x2B)
加速度计Z轴的44和45(0x2C和0x2D)
对于磁场,您需要磁传感器寄存器:
X轴磁场强度为40和41(0x28和0x29)
Y轴磁场强度的42和43(0x2A和0x2B)
Z轴磁场强度的44和45(0x2C和0x2D)
这些都是二进制补码格式,最低有效字节在前。
由于几乎所有的微控制器都对二进制整数使用二进制补码格式(STM32确实如此,ARM和AVR包括所有Arduino一样),因此您可以编写五个简单的辅助函数。 在伪C中:
static int16_t temperature;
static int16_t gyro_x, gyro_y, gyro_z;
static int16_t accel_x, accel_y, accel_z;
static int16_t mag_x, mag_y, mag_z;
static uint8_t buf[6];
static void update_temperature(void)
{
/* Read 2 bytes from registers 0x15 and 0x16 (21 and 22)
from the accelerometer/gyroscope device, to buf[] */
temperature = (int16_t)((((unsigned int)buf[1]) << 8) | (unsigned int)(buf[0]));
}
static void update_gyro(void)
{
/* Read 6 bytes from registers 0x18..0x1D (24 through 29)
from the accelerometer/gyroscope device, to buf[] */
gyro_x = (int16_t)((((unsigned int)buf[1]) << 8) | (unsigned int)(buf[0]));
gyro_y = (int16_t)((((unsigned int)buf[3]) << 8) | (unsigned int)(buf[2]));
gyro_z = (int16_t)((((unsigned int)buf[5]) << 8) | (unsigned int)(buf[4]));
}
static void update_accel(void)
{
/* Read 6 bytes from registers 0x28..0x2D (40 through 45)
from the accelerometer/gyroscope device, to buf[] */
accel_x = (int16_t)((((unsigned int)buf[1]) << 8) | (unsigned int)(buf[0]));
accel_y = (int16_t)((((unsigned int)buf[3]) << 8) | (unsigned int)(buf[2]));
accel_z = (int16_t)((((unsigned int)buf[5]) << 8) | (unsigned int)(buf[4]));
}
static void update_mag(void)
{
/* Read 6 bytes from registers 0x28..0x2D (40 through 45)
from the magnetic sensor device, to buf[] */
mag_x = (int16_t)((((unsigned int)buf[1]) << 8) | (unsigned int)(buf[0]));
mag_y = (int16_t)((((unsigned int)buf[3]) << 8) | (unsigned int)(buf[2]));
mag_z = (int16_t)((((unsigned int)buf[5]) << 8) | (unsigned int)(buf[4]));
}
static void update_all(void)
{
update_temperature();
update_gyro();
update_accel();
update_mag();
}
分配看起来很时髦,但是编译器应该优化它们以使机器代码合理。
您可能需要编写一个辅助函数来进行实际读取(或者可能是三个函数;一个函数用于将2个字节从加速度计/陀螺仪设备读取到buf [],一个函数将6个字节从加速度计/陀螺仪设备读取到buf [],以及一个用于从磁传感器设备向buf []读取6个字节的寄存器,所有这些都是从连续寄存器中提供的,该寄存器作为函数的参数提供)。
这种方法使用26字节的RAM,并且应适用于所有8位(AVR)和32位(STM32,ARM)微控制器。 上面的代码对微控制器的字节顺序(字节序)不敏感。
如果您的设备通过USB或串行方式将陀螺仪,加速度计和磁传感器值发送到计算机,则需要知道输出值的字节顺序(字节序)。
传感器本身首先以最低有效字节的形式提供它们。 据我所知,STM32也是little-endian,因此它也应该首先提供最低有效字节。
因此,假设您从设备接收到18*N
字节,首先是陀螺仪轴,然后是加速度计轴,最后是磁传感器轴读数。 以下应该将这些值转换为带符号的整数,以便于操作:
#include <stdlib.h>
#include <inttypes.h>
static inline void extract16toint(int *const to,
const unsigned char *const from,
const size_t n,
const size_t stride)
{
const unsigned char *const end = from + n * stride;
const unsigned char *src = from;
int *dst;
while (src < end) {
*(dst++) = (int16_t)( (unsigned int)(src[0])
| ((unsigned int)(src[1]) << 8) );
src += stride;
}
}
static void extract_gyroX(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 0, n, 18);
}
static void extract_gyroY(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 2, n, 18);
}
static void extract_gyroZ(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 4, n, 18);
}
static void extract_accelX(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 6, n, 18);
}
static void extract_accelY(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 8, n, 18);
}
static void extract_accelZ(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 10, n, 18);
}
static void extract_magX(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 12, n, 18);
}
static void extract_magY(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 14, n, 18);
}
static void extract_magZ(int *const to,
const unsigned char *const data,
const size_t n)
{
extract16toint(to, data + 16, n, 18);
}
在OP的情况下,调用类似
int *accelX = malloc(300 * sizeof (int));
extract_accelX(accelX, rawData, 300);
应该管用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.