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

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-42605运动传感器采用2.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接口描述
    SPI接口描述
    由上述描述可知:
  • SPI传输时,先传输字节高位,再传输字节低位.
  • 在时钟上升沿时锁存数据,下降沿时传输数据
  • SPI时钟最快24MHZ
  • 在执行寄存器进行读写操作时,寄存器的最高位用来表示读写

源码实现

使用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;
    hspi1.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 上下载

结束语

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

  • 24
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 148
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 148
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值