8bit(两个值)数组到16bit数组(一个值)

时间:2018-08-22 13:10:10

标签: c arrays stm32

我正在从传感器读取数据,该传感器将它们作为两个8位值发送,用户必须将它们转换为一个带符号的16位值。我将这些值保存到一个5400个元素的数组中(传感器是加速度计+陀螺仪+磁力计,所以是9个轴,所以最后每个轴都有300个值)。所以可以说我需要从加速度计的X轴读取数据。在我的数组中,我将它们保存在前两个位置,因此我的accX读数分别位于索引0,1,然后是18,19,然后是36,37,依此类推..... 现在,我需要将它们提取到具有300个元素的新16位数组中,这些元素将仅代表加速度计的X轴。我的想法如下:

constructor(private route: ActivatedRoute) {}
ngOnInit() {
    this.sessionId = this.route.snapshot.queryParams['token']

}

我的AccX数组中的值是我不希望出现的值。知道可能出了什么问题吗?传感器是LSM9DS1。

编辑:对不起,我没有提供有关该设备的更多信息。我肯定知道这可行:

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);

我还检查了rawData数组,它包含正确的数据。当我尝试将数据填充到AccX阵列时出错

1 个答案:

答案 0 :(得分:3)

查看datasheet。本质上,一个包装中有两个独立的设备。

您需要加速度计/陀螺仪设备寄存器:

  • 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确实如此,包括所有Arduino的ARM和AVR一样),因此您可以编写五个简单的辅助函数。在伪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);

应该工作。