239 lines
6.7 KiB
C
239 lines
6.7 KiB
C
|
|
/*
|
||
|
|
* Acc_ICM20600.c
|
||
|
|
*
|
||
|
|
* Created on: July 12, 2020
|
||
|
|
* Author: lqh
|
||
|
|
*/
|
||
|
|
#include "Imu_ICM20600.h"
|
||
|
|
#include "main.h"
|
||
|
|
|
||
|
|
/* ICM20600 registers addresses */
|
||
|
|
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:
|
||
|
|
#define CONFIG 0x1A //低通滤波频率,典型值:
|
||
|
|
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:
|
||
|
|
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值
|
||
|
|
#define ACCEL_CONFIG1 0x1D //加速计自检、测量范围及高通滤波频率,典型值:
|
||
|
|
#define FIFO_EN 0x23
|
||
|
|
#define FIFO_WM_TH1 0x60
|
||
|
|
#define FIFO_WM_TH2 0x61
|
||
|
|
#define FIFO_COUNTH 0x72
|
||
|
|
#define FIFO_COUNTL 0x73
|
||
|
|
#define FIFO_R_W 0x74
|
||
|
|
|
||
|
|
#define ACCEL_XOUT_H 0x3B //加速度计 x轴加速度 高8位
|
||
|
|
#define ACCEL_XOUT_L 0x3C //加速度计 x轴加速度 低8位
|
||
|
|
#define ACCEL_YOUT_H 0x3D //加速度计 y轴加速度 高8位
|
||
|
|
#define ACCEL_YOUT_L 0x3E //加速度计 y轴加速度 低8位
|
||
|
|
#define ACCEL_ZOUT_H 0x3F //加速度计 z轴加速度 高8位
|
||
|
|
#define ACCEL_ZOUT_L 0x40 //加速度计 z轴加速度 低8位
|
||
|
|
#define TEMP_OUT_H 0x41 //温度 高8位
|
||
|
|
#define TEMP_OUT_L 0x42 //温度 低8位
|
||
|
|
#define GYRO_XOUT_H 0x43 //陀螺仪 x轴陀螺仪 高8位
|
||
|
|
#define GYRO_XOUT_L 0x44 //陀螺仪 x轴陀螺仪 低8位
|
||
|
|
#define GYRO_YOUT_H 0x45 //陀螺仪 y轴陀螺仪 高8位
|
||
|
|
#define GYRO_YOUT_L 0x46 //陀螺仪 y轴陀螺仪 低8位
|
||
|
|
#define GYRO_ZOUT_H 0x47 //陀螺仪 z轴陀螺仪 高8位
|
||
|
|
#define GYRO_ZOUT_L 0x48 //陀螺仪 z轴陀螺仪 低8位
|
||
|
|
|
||
|
|
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x11,只读)
|
||
|
|
#define USER_CONTROL 0x6A //0x10 I2C_IF_DIS ENABLE
|
||
|
|
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
|
||
|
|
|
||
|
|
// WHOAMI values
|
||
|
|
#define MPU_WHOAMI_20600 0x11
|
||
|
|
|
||
|
|
|
||
|
|
/** 初始化ADXL加速度计*/
|
||
|
|
int Imu_ICM20600_init(Imu_ICM20600_t *Imu, const char *name, SPI_DEV_t *dev,
|
||
|
|
GPIO_EXIT_t *exti) {
|
||
|
|
|
||
|
|
uint8_t ChipId; //Read ICM20600 Chip Infomation
|
||
|
|
int rslt;
|
||
|
|
uint8_t TxdBuf[4];
|
||
|
|
uint8_t RxdBuf[4];
|
||
|
|
|
||
|
|
rslt = 0;
|
||
|
|
|
||
|
|
Imu->name = name;
|
||
|
|
Imu->_dev = dev;
|
||
|
|
Imu->exti = exti;
|
||
|
|
|
||
|
|
Imu->Accx = 0;
|
||
|
|
Imu->Accy = 0;
|
||
|
|
Imu->Accz = 0;
|
||
|
|
|
||
|
|
Imu->Gyrox = 0;
|
||
|
|
Imu->Gyroy = 0;
|
||
|
|
Imu->Gyroz = 0;
|
||
|
|
|
||
|
|
Imu->At = 0;
|
||
|
|
Imu->read_cnt = 0;
|
||
|
|
Imu->exti->cnt = 0;
|
||
|
|
|
||
|
|
Imu->cnt = 0;
|
||
|
|
Imu->last_cnt = 0;
|
||
|
|
Imu->pps = 0;
|
||
|
|
|
||
|
|
Imu->acc_lsb_per_g = 2048.0f;
|
||
|
|
Imu->gyro_lsb_per_deg_sec = 16.38;
|
||
|
|
|
||
|
|
SPI_DEV_begin(Imu->_dev, -1);
|
||
|
|
|
||
|
|
/* Quick verification test for boards */
|
||
|
|
TxdBuf[0] = 0x80 | WHO_AM_I; //Read ChipId
|
||
|
|
TxdBuf[1] = 0x00; //Read ChipId
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, RxdBuf, 2, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
ChipId = RxdBuf[1];
|
||
|
|
|
||
|
|
//If Target Chip is ICM20600, Set Chip Range & Turn on Accelerometer Mode
|
||
|
|
if (ChipId == MPU_WHOAMI_20600) {
|
||
|
|
|
||
|
|
//开始配置
|
||
|
|
TxdBuf[0] = PWR_MGMT_1; //Write ICM20600 PWR_MGMT_1
|
||
|
|
TxdBuf[1] = 0x00; //reset imu
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
TxdBuf[0] = ACCEL_CONFIG; //Write ICM20600 ACCEL_CONFIG
|
||
|
|
TxdBuf[1] = 0x18; //ACC ±16G
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
TxdBuf[0] = CONFIG; //Write ICM20600 CONFIG
|
||
|
|
TxdBuf[1] = 0x07; //Gyroscope Rate 8k hz
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
TxdBuf[0] = SMPLRT_DIV; //Write ICM20600 SMPLRT_DIV
|
||
|
|
TxdBuf[1] = 0x00; //INTERNAL_SAMPLE_RATE = 1kHz
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
TxdBuf[0] = GYRO_CONFIG; //Write ICM20600 GYRO_CONFIG
|
||
|
|
TxdBuf[1] = 0x18; //Gyro ±2000 dps
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
TxdBuf[0] = ACCEL_CONFIG1; //Write ICM20600 ACCEL_CONFIG1
|
||
|
|
TxdBuf[1] = 0x08; //Accelerometer rate 1k hz
|
||
|
|
SPI_DEV_select(dev);
|
||
|
|
SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2);
|
||
|
|
SPI_DEV_unselect(dev);
|
||
|
|
|
||
|
|
} else {
|
||
|
|
rslt = -1;
|
||
|
|
}
|
||
|
|
SPI_DEV_end(Imu->_dev);
|
||
|
|
|
||
|
|
return rslt;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/** 读取ICM-20600值 */
|
||
|
|
bool Imu_ICM20600_update(Imu_ICM20600_t *Imu) {
|
||
|
|
uint8_t TxdBuf[15];
|
||
|
|
uint8_t RxdBuf[15];
|
||
|
|
int i;
|
||
|
|
int16_t TempAcceleratorData;
|
||
|
|
bool rslt;
|
||
|
|
|
||
|
|
if (SPI_DEV_begin(Imu->_dev, 0)) //进入临界区
|
||
|
|
{
|
||
|
|
TxdBuf[0] = ((ACCEL_XOUT_H | 0x80)); //Read
|
||
|
|
for (i = 1; i < 15; i++) {
|
||
|
|
TxdBuf[i] = 0x00; //Dummy Byte 虚拟字节
|
||
|
|
}
|
||
|
|
SPI_DEV_select(Imu->_dev);
|
||
|
|
rslt = SPI_DEV_transfer(Imu->_dev, TxdBuf, 15, RxdBuf, 15, 3);
|
||
|
|
SPI_DEV_unselect(Imu->_dev);
|
||
|
|
|
||
|
|
SPI_DEV_end(Imu->_dev); //退出临界区
|
||
|
|
|
||
|
|
Imu->exti->cnt = 0; //中断计数清零
|
||
|
|
|
||
|
|
if (rslt) {
|
||
|
|
Imu->cnt++;
|
||
|
|
taskENTER_CRITICAL();
|
||
|
|
Imu->read_cnt++;
|
||
|
|
|
||
|
|
/** Data combination for Acc Raw Data */
|
||
|
|
TempAcceleratorData = ((RxdBuf[1] << 8) | (RxdBuf[2]));
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->Accx = (float)TempAcceleratorData/Imu->acc_lsb_per_g; //Accumulated Value of ax x轴
|
||
|
|
|
||
|
|
//Data combination forAy Raw Data
|
||
|
|
TempAcceleratorData = ((RxdBuf[3] << 8) | (RxdBuf[4]));
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->Accy = (float)TempAcceleratorData/Imu->acc_lsb_per_g; //Accumulated Value of ay y轴
|
||
|
|
|
||
|
|
//Data combination for Az Raw Data
|
||
|
|
TempAcceleratorData = ((RxdBuf[5] << 8) | (RxdBuf[6]));
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->Accz = (float)TempAcceleratorData/Imu->acc_lsb_per_g; //Accumulated Value of az z轴
|
||
|
|
|
||
|
|
//Data combination for Temperature Raw Data
|
||
|
|
TempAcceleratorData = ((RxdBuf[7] << 8) | RxdBuf[8]);
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->At = (float)((double)TempAcceleratorData/333.87+21); // IMU Value of Temperature 温度
|
||
|
|
|
||
|
|
|
||
|
|
/** Data combination for Gyro Raw Data */
|
||
|
|
TempAcceleratorData = ((RxdBuf[9] << 8) | (RxdBuf[10]));
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->Gyrox = (float)TempAcceleratorData/Imu->gyro_lsb_per_deg_sec; //Gyro Value of ax x轴
|
||
|
|
|
||
|
|
//Data combination forAy Raw Data
|
||
|
|
TempAcceleratorData = ((RxdBuf[11] << 8) | (RxdBuf[12]));
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->Gyroy = (float)TempAcceleratorData/Imu->gyro_lsb_per_deg_sec; //Gyro Value of ay y轴
|
||
|
|
|
||
|
|
//Data combination for Az Raw Data
|
||
|
|
TempAcceleratorData = ((RxdBuf[13] << 8) | (RxdBuf[14]));
|
||
|
|
if ((TempAcceleratorData & 0x0800) != 0) //Sign-extending for raw data
|
||
|
|
{
|
||
|
|
TempAcceleratorData |= 0xF000;
|
||
|
|
}
|
||
|
|
Imu->Gyroz = (float)TempAcceleratorData/Imu->gyro_lsb_per_deg_sec; //Gyro Value of az z轴
|
||
|
|
taskEXIT_CRITICAL();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
rslt = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return rslt;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
void Imu_ICM20600_stats(Imu_ICM20600_t *Imu) {
|
||
|
|
Imu->pps = Imu->cnt - Imu->last_cnt;
|
||
|
|
Imu->last_cnt = Imu->cnt;
|
||
|
|
}
|