锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

ICM-42605 6轴MEMS加速度计陀螺仪运动传感器数据的读取

时间:2022-12-15 01:30:00 ps4稳定传感器传感器afs60b48v电流传感器

ICM42605传感器简介

ICM426056轴MEMS运动传感器是集3轴陀螺仪和3轴加速度计于一体的运动跟踪器件。陀螺仪支持8个可编程满量程范围设置(从±15.625dps到±2000dps)。加速度计支持8个可编程满量程范围设置(从±2g到±16g)。运动传感器还包括2KB的FIFO,可降低串行总线接口的流量和功耗。通过允许系统处理器突然读取传感器数据,然后进入低功耗模式。
ICM-42605运动传感器具有可编程数字
滤波器、可编程中断、嵌入式温度传感器、20,000g抗冲击能力和EIS FSYNC支持。还包括运动传感器I3CSM、SPI和I2C串行接口,1.71V至3.6V VDD工作电压范围和1.71V至3.6V独立VDDIO工作电压范围。ICM-242605运动传感器.5mm x 3mm x 0.91mm 14引脚LGA封装。典型应用包括智能手机、平板电脑、可穿戴传感器、物联网、虚拟现实耳机和控制器。

ICM42605传感器特性

  • 陀螺仪的可编程范围为±15.625°/sec、±31.25°/sec、±62.5°/sec、±125°/sec、±250°/sec、±500°/sec、±1000°/sec和±2000°/sec
  • 加速度计的可编程满量范围为±2g、±4g、±8g和±16g
  • 低噪声模式6轴电流消耗0.65mA
    1. 陀螺仪噪音为3.8mdps/√Hz
    2. 加速度计的噪为70μg/√Hz
  • 2KB FIFO可以减少串行总线接口上的流量
  • 稳定帧同步的电子图像 (EIS FSYNC) 支持
  • 用户可编程陀螺仪、加速度计和温度传感器的数字滤波器
  • 可编程中断用户
  • 数字输出温度传感器
  • 20,000g抗冲击能力
  • 高级计步器和事件检测 – neXt gen (APEX) 运动功能:
    1. 计步器
    2. 倾斜检测
    3. 提醒/睡眠
    4. 轻敲感测
    5. 运动唤醒
    6. 大幅运动检测
  • 12.5MHz I3CSM、1MHz I2C和24MHz SPI主机接口
  • 1.8V标称VDD工作电压
  • 符合RoHS指令的绿色器件

本文使用SPI接口读取ICM42605的数据

硬件接口

  1. 使用SPI 连接传感器的原理图
    SPI连接原理图
  2. 传感器SPI接口描述

    以上描述可知:

源码实现

使用STM32G030F6单片机硬件SPI1读写传感器

  1. STM32G030F6 硬件SPI1的配置
void hal_Spi1Master_Init(void) { 
              GPIO_InitTypeDef GPIO_InitStruct;     /* USER CODE BEGIN SPI1_Init 0 */     /* Peripheral clock enable */     __HAL_RCC_SPI1_CLK_ENABLE();      __HAL_RCC_GPIOA_CLK_ENABLE();     /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */     GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_6 | GPIO_PIN_7;     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;     GPIO_InitStruct.Pull = GPIO_NOPULL;     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;     GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);     /* USER CODE END SPI1_Init 0 */      /* USER CODE BEGIN SPI1_Init 1 */      /* USER CODE END SPI1_Init 1 */     /* SPI1 parameter configuration*/     hspi1.Instance = SPI1;     hspi1.Init.Mode = SPI_MODE_MASTER.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    /* SPI_POLARITY_LOW SPI_POLARITY_HIGH */
    hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
    hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
    hspi1.Init.NSS = SPI_NSS_SOFT;
    /* SPI_BAUDRATEPRESCALER_2: 32MBits/s SPI_BAUDRATEPRESCALER_4: 16MBits/s SPI_BAUDRATEPRESCALER_8: 8MBits/s SPI_BAUDRATEPRESCALER_16: 4MBits/s SPI_BAUDRATEPRESCALER_32: 2MBits/s SPI_BAUDRATEPRESCALER_64: 1MBits/s SPI_BAUDRATEPRESCALER_128: 500KBits/s SPI_BAUDRATEPRESCALER_256: 250KBits/s */
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 7;
    hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    if(HAL_SPI_Init(&hspi1) != HAL_OK)
    { 
        
        Error_Handler();
    }
    /* USER CODE BEGIN SPI1_Init 2 */

    /* USER CODE END SPI1_Init 2 */

}
  1. 传感器读写寄存器函数的实现
uint8_t hal_Spi1_ReadWriteByte(uint8_t txdata)
{ 
        
    uint8_t rxdata = 0;
    HAL_SPI_TransmitReceive(&hspi1, &txdata, &rxdata, 1, 5); //超时5ms
    return rxdata;
}

#if defined(ICM_USE_HARD_SPI)
#define ICM_RCC_SPIX_CS() __HAL_RCC_GPIOA_CLK_ENABLE()
#define ICM_PORT_SPIX_CS GPIOA
#define ICM_PIN_SPIX_CS GPIO_PIN_4
#define ICM_SPI_CS_LOW() HAL_GPIO_WritePin(ICM_PORT_SPIX_CS, ICM_PIN_SPIX_CS, GPIO_PIN_RESET)
#define ICM_SPI_CS_HIGH() HAL_GPIO_WritePin(ICM_PORT_SPIX_CS, ICM_PIN_SPIX_CS, GPIO_PIN_SET)


/******************************************************************************* * 名 称: bsp_IcmSpixCsInit * 功 能: Icm SPI的CS控制引脚初始化 * 入口参数: 无 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
void bsp_IcmSpixCsInit(void)
{ 
        
    GPIO_InitTypeDef GPIO_InitStruct = { 
        0};

    /* GPIO Ports Clock Enable */
    ICM_RCC_SPIX_CS();

    /*Configure GPIO pins */
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Pin = ICM_PIN_SPIX_CS;
    HAL_GPIO_Init(ICM_PORT_SPIX_CS, &GPIO_InitStruct);
    HAL_GPIO_WritePin(ICM_PORT_SPIX_CS, ICM_PIN_SPIX_CS, GPIO_PIN_SET);
}

/******************************************************************************* * 名 称: Icm_Spi_ReadWriteNbytes * 功 能: 使用SPI读写n个字节 * 入口参数: pBuffer: 写入的数组 len:写入数组的长度 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
static void Icm_Spi_ReadWriteNbytes(uint8_t* pBuffer, uint8_t len)
{ 
        
    uint8_t i = 0;

#if defined(ICM_USE_HARD_SPI)
    for(i = 0; i < len; i ++)
    { 
        
        *pBuffer = hal_Spi1_ReadWriteByte(*pBuffer);
        pBuffer++;
    }
#endif

}
#endif

/******************************************************************************* * 名 称: icm42605_read_reg * 功 能: 读取单个寄存器的值 * 入口参数: reg: 寄存器地址 * 出口参数: 当前寄存器地址的值 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: 使用SPI读取寄存器时要注意:最高位为读写位,详见datasheet page50. *******************************************************************************/
static uint8_t icm42605_read_reg(uint8_t reg)
{ 
        
    uint8_t regval = 0;

#if defined(ICM_USE_HARD_SPI)
    ICM_SPI_CS_LOW();
    reg |= 0x80;
    /* 写入要读的寄存器地址 */
    Icm_Spi_ReadWriteNbytes(&reg, 1);
    /* 读取寄存器数据 */
    Icm_Spi_ReadWriteNbytes(&regval, 1);
    ICM_SPI_CS_HIGH();
#elif defined(ICM_USE_HARD_I2C)

#endif

    return regval;
}

/******************************************************************************* * 名 称: icm42605_read_regs * 功 能: 连续读取多个寄存器的值 * 入口参数: reg: 起始寄存器地址 *buf数据指针,uint16_t len长度 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: 使用SPI读取寄存器时要注意:最高位为读写位,详见datasheet page50. *******************************************************************************/
static void icm42605_read_regs(uint8_t reg, uint8_t* buf, uint16_t len)
{ 
        
#if defined(ICM_USE_HARD_SPI)
    reg |= 0x80;
    ICM_SPI_CS_LOW();
    /* 写入要读的寄存器地址 */
    Icm_Spi_ReadWriteNbytes(&reg, 1);
    /* 读取寄存器数据 */
    Icm_Spi_ReadWriteNbytes(buf, len);
    ICM_SPI_CS_HIGH();
#elif defined(ICM_USE_HARD_I2C)
#endif
}


/******************************************************************************* * 名 称: icm42605_write_reg * 功 能: 向单个寄存器写数据 * 入口参数: reg: 寄存器地址 value:数据 * 出口参数: 0 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: 使用SPI读取寄存器时要注意:最高位为读写位,详见datasheet page50. *******************************************************************************/
static uint8_t icm42605_write_reg(uint8_t reg, uint8_t value)
{ 
        
#if defined(ICM_USE_HARD_SPI)
    ICM_SPI_CS_LOW();
    /* 写入要读的寄存器地址 */
    Icm_Spi_ReadWriteNbytes(&reg, 1);
    /* 读取寄存器数据 */
    Icm_Spi_ReadWriteNbytes(&value, 1);
    ICM_SPI_CS_HIGH();
#elif defined(ICM_USE_HARD_I2C)
#endif
    return 0;
}
  1. 传感器初始化的实现
float bsp_Icm42605GetAres(uint8_t Ascale)
{ 
        
    switch(Ascale)
    { 
        
    // Possible accelerometer scales (and their register bit settings) are:
    // 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11).
    case AFS_2G:
        accSensitivity = 2000 / 32768.0f;
        break;
    case AFS_4G:
        accSensitivity = 4000 / 32768.0f;
        break;
    case AFS_8G:
        accSensitivity = 8000 / 32768.0f;
        break;
    case AFS_16G:
        accSensitivity = 16000 / 32768.0f;
        break;
    }

    return accSensitivity;
}

float bsp_Icm42605GetGres(uint8_t Gscale)
{ 
        
    switch(Gscale)
    { 
        
    case GFS_15_125DPS:
        gyroSensitivity = 15.125f / 32768.0f;
        break;
    case GFS_31_25DPS:
        gyroSensitivity = 31.25f / 32768.0f;
        break;
    case GFS_62_5DPS:
        gyroSensitivity = 62.5f / 32768.0f;
        break;
    case GFS_125DPS:
        gyroSensitivity = 125.0f / 32768.0f;
        break;
    case GFS_250DPS:
        gyroSensitivity = 250.0f / 32768.0f;
        break;
    case GFS_500DPS:
        gyroSensitivity = 500.0f / 32768.0f;
        break;
    case GFS_1000DPS:
        gyroSensitivity = 1000.0f / 32768.0f;
        break;
    case GFS_2000DPS:
        gyroSensitivity = 2000.0f / 32768.0f;
        break;
    }
    return gyroSensitivity;
}

/******************************************************************************* * 名 称: bsp_Icm42605RegCfg * 功 能: Icm42605 寄存器配置 * 入口参数: 无 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: *******************************************************************************/
int8_t bsp_Icm42605RegCfg(void)
{ 
        
    uint8_t reg_val = 0;
    /* 读取 who am i 寄存器 */
    reg_val = icm42605_read_reg(ICM42605_WHO_AM_I);

    icm42605_write_reg(ICM42605_REG_BANK_SEL, 0); //设置bank 0区域寄存器
    icm42605_write_reg(ICM42605_REG_BANK_SEL, 0x01); //软复位传感器
    ICM42605DelayMs(100);


    if(reg_val == ICM42605_ID)
    { 
        
        icm42605_write_reg(ICM42605_REG_BANK_SEL, 1); //设置bank 1区域寄存器
        icm42605_write_reg(ICM42605_INTF_CONFIG4, 0x02); //设置为4线SPI通信

        icm42605_write_reg(ICM42605_REG_BANK_SEL, 0); //设置bank 0区域寄存器
        icm42605_write_reg(ICM42605_FIFO_CONFIG, 0x40); //Stream-to-FIFO Mode(page61)


        reg_val = icm42605_read_reg(ICM42605_INT_SOURCE0);
        icm42605_write_reg(ICM42605_INT_SOURCE0, 0x00);
        icm42605_write_reg(ICM42605_FIFO_CONFIG2, 0x00); // watermark
        icm42605_write_reg(ICM42605_FIFO_CONFIG3, 0x02); // watermark
        icm42605_write_reg(ICM42605_INT_SOURCE0, reg_val);
        icm42605_write_reg(ICM42605_FIFO_CONFIG1, 0x63); // Enable the accel and gyro to the FIFO

        icm42605_write_reg(ICM42605_REG_BANK_SEL, 0x00);
        icm42605_write_reg(ICM42605_INT_CONFIG, 0x36);

        icm42605_write_reg(ICM42605_REG_BANK_SEL, 0x00);
        reg_val = icm42605_read_reg(ICM42605_INT_SOURCE0);
        reg_val |= (1 << 2); //FIFO_THS_INT1_ENABLE
        icm42605_write_reg(ICM42605_INT_SOURCE0, reg_val);

        bsp_Icm42605GetAres(AFS_8G);
        icm42605_write_reg(ICM42605_REG_BANK_SEL, 0x00);
        reg_val = icm42605_read_reg(ICM42605_ACCEL_CONFIG0);//page74
        reg_val |= (AFS_8G << 5);   //量程 ±8g
        reg_val |= (AODR_50Hz);     //输出速率 50HZ
        icm42605_write_reg(ICM42605_ACCEL_CONFIG0, reg_val);

        bsp_Icm42605GetGres(GFS_1000DPS);
        icm42605_write_reg(ICM42605_REG_BANK_SEL, 0x00);
        reg_val = icm42605_read_reg(ICM42605_GYRO_CONFIG0);//page73
        reg_val |= (GFS_1000DPS << 5);   //量程 ±1000dps
        reg_val |= (GODR_50Hz);     //输出速率 50HZ
        icm42605_write_reg(ICM42605_GYRO_CONFIG0, reg_val);

        icm42605_write_reg(ICM42605_REG_BANK_SEL, 0x00);
        reg_val = icm42605_read_reg(ICM42605_PWR_MGMT0); //读取PWR—MGMT0当前寄存器的值(page72)
        reg_val &= ~(1 << 5);//使能温度测量
        reg_val |= ((3) << 2);//设置GYRO_MODE 0:关闭 1:待机 2:预留 3:低噪声
        reg_val |= (3);//设置ACCEL_MODE 0:关闭 1:关闭 2:低功耗 3:低噪声
        icm42605_write_reg(ICM42605_PWR_MGMT0, reg_val);
        ICM42605DelayMs(1); //操作完PWR—MGMT0寄存器后 200us内不能有任何读写寄存器的操作

        return 0;
    }
    return -1;
}
  1. 读取传感器内部温度传感器
/******************************************************************************* * 名 称: bsp_IcmGetTemperature * 功 能: 读取Icm42605 内部传感器温度 * 入口参数: 无 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: datasheet page62 *******************************************************************************/
int8_t bsp_IcmGetTemperature(int16_t* pTemp)
{ 
        
    uint8_t buffer[2] = { 
        0};

    icm42605_read_regs(ICM42605_TEMP_DATA1, buffer, 2);

    *pTemp = (int16_t)(((int16_t)((buffer[0] << 8) | buffer[1])) / 132.48 + 25);
    return 0;
}
  1. 读取传感器加速度的值
/******************************************************************************* * 名 称: bsp_IcmGetAccelerometer * 功 能: 读取Icm42605 加速度的值 * 入口参数: 三轴加速度的值 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: datasheet page62 *******************************************************************************/
int8_t bsp_IcmGetAccelerometer(icm42605RawData_t* accData)
{ 
        
    uint8_t buffer[6] = { 
        0};

    icm42605_read_regs(ICM42605_ACCEL_DATA_X1, buffer, 6);

    accData->x = ((uint16_t)buffer[0] << 8) | buffer[1];
    accData->y = ((uint16_t)buffer[2] << 8) | buffer[3];
    accData->z = ((uint16_t)buffer[4] << 8) | buffer[5];

    accData->x = (int16_t)(accData->x * accSensitivity);
    accData->y = (int16_t)(accData->y * accSensitivity);
    accData->z = (int16_t)(accData->z * accSensitivity);

    return 0;
}

  1. 读取传感器陀螺仪的值
/******************************************************************************* * 名 称: bsp_IcmGetGyroscope * 功 能: 读取Icm42605 陀螺仪的值 * 入口参数: 三轴陀螺仪的值 * 出口参数: 无 * 作  者: Roger-WY. * 创建日期: 2021-05-21 * 修 改: * 修改日期: * 备 注: datasheet page63 *******************************************************************************/
int8_t bsp_IcmGetGyroscope(icm42605RawData_t* GyroData)
{ 
        
    uint8_t buffer[6] = { 
        0};

    icm42605_read_regs(ICM42605_GYRO_DATA_X1, buffer, 6);

    GyroData->x = ((uint16_t)buffer[0] << 8) | buffer[1];
    GyroData->y = ((uint16_t)buffer[2] << 8) | buffer[3];
    GyroData->z = ((uint16_t)buffer[4] << 8) | buffer[5];

    GyroData->x = (int16_t)(GyroData->x * gyroSensitivity);
    GyroData->y = (int16_t)(GyroData->y * gyroSensitivity);
    GyroData->z = (int16_t)(GyroData->z * gyroSensitivity);
    return 0;
}

调用以上函数即可实现对应的功能,已经实测过,没有问题.

完整的工程

可点击此处下载完整工程STM32G030硬件SPI读取ICM42605六轴运动传感器(有积分或者是会员的小伙伴可以支持一下!

PS:鉴于积分实在有点糟心,后面我把工程上传到 gitee 上了,没有积分的小伙伴可以直接去 gitee 上下载

结束语

如果觉得文章对您有帮助,请关注点赞,谢谢!

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章