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封装。典型应用包括智能手机、平板电脑、可穿戴传感器、物联网、虚拟现实耳机和控制器。
使用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 */
}
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(®, 1);
/* 读取寄存器数据 */
Icm_Spi_ReadWriteNbytes(®val, 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(®, 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(®, 1);
/* 读取寄存器数据 */
Icm_Spi_ReadWriteNbytes(&value, 1);
ICM_SPI_CS_HIGH();
#elif defined(ICM_USE_HARD_I2C)
#endif
return 0;
}
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;
}
/*******************************************************************************
* 名 称: 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;
}
/*******************************************************************************
* 名 称: 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;
}
/*******************************************************************************
* 名 称: 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 上下载
如果觉得文章对您有帮助,请关注、点赞,谢谢!