【MEMS传感器】ICM20690六轴传感器SPI驱动

2023-05-16

此驱动适合ICM206xx系列,基本上更改who_am_i寄存器和一些特殊功能寄存器就可以,这里以获取角速度与陀螺为例。

初始化调用两个函数:

	ICM20690_CHIP_INIT();	
	ICM20690_CHIP_startup();	//芯片,acc,gro,enable

获取normal模式下数据调用

        ICM20690_GetACC();
	ICM20690_GetGYRO();

 


   
#ifndef ICM20690_H_
#define ICM20690_H_
#include "include.h"

#define  ICM20690 1

#if ICM20690
/* Hardware registers needed by driver. */
struct sensor_reg_20690 {
	unsigned char who_am_i;
	unsigned char rate_div;
	unsigned char lpf;
	//    unsigned char prod_id;
	unsigned char xg_offs_usr;
	unsigned char yg_offs_usr;
	unsigned char zg_offs_usr;
	unsigned char user_ctrl;
	unsigned char fifo_en;
	unsigned char gyro_cfg;
	unsigned char accel_cfg;
	unsigned char accel_cfg2;
	unsigned char lp_mode_cfg;
	unsigned char motion_thr;
	//    unsigned char motion_dur;
	unsigned char fifo_count_h;
	unsigned char fifo_r_w;
	unsigned char raw_gyro;
	unsigned char raw_accel;
	unsigned char temp;
	unsigned char int_enable;
	//    unsigned char dmp_int_status;
	unsigned char int_status;
	unsigned char accel_intel;
	unsigned char pwr_mgmt_1;
	unsigned char pwr_mgmt_2;
	unsigned char int_pin_cfg;
	//    unsigned char mem_r_w;
	unsigned char xa_offset;
	unsigned char ya_offset;
	unsigned char za_offset;
	//    unsigned char i2c_mst;
	//    unsigned char bank_sel;
	//    unsigned char mem_start_addr;
	unsigned char prgm_start_h;
	//    unsigned char fifo_wm_th;
	unsigned char signal_reset;
	//    unsigned char st_gyro;
	unsigned char st_accel;
};


void ICM20690_read_ID(void);
void sensor_dump(void);
void ICM20690_CHIP_INIT(void);
void ICM20690_CHIP_startup(void);
void ICM20690_CHIP_POWERON(void);
void ICM20690_CHIP_POWEROFF(void);
void ICM20690_ACC_POWERON(void);
void ICM20690_ACC_POWEROFF(void);
void ICM20690_GYRO_POWERON(void);
void ICM20690_GYRO_POWEROFF(void);
void ICM20690_ACC_ENABLE(void);
void ICM20690_GYRO_ENABLE(void);
void ICM20690_SET_ACC_GYRO_ODR(uint32_t HZ);
void ICM20690_GetACC(void);
void ICM20690_GetGYRO(void);

#endif

#endif /* ICM20690_H_ */

 

 

 

#include "ICM20690.h"

//
#if ICM20690
uint8_t read_ICM20690_ID=0xff;
const struct sensor_reg_20690 ICM20690_reg = {
	.who_am_i       = 0x75,
	.rate_div       = 0x19,
	.lpf            = 0x1A,
	//    .prod_id        = 0x0C,
	.xg_offs_usr    = 0x13,
	.yg_offs_usr    = 0x15,
	.zg_offs_usr    = 0x17,
	.user_ctrl      = 0x6A,
	.fifo_en        = 0x23,
	.gyro_cfg       = 0x1B,
	.accel_cfg      = 0x1C,
	.accel_cfg2     = 0x1D,
	.lp_mode_cfg    = 0x1E,
	.motion_thr     = 0x1F,
	//    .motion_dur     = 0x20,
	.fifo_count_h   = 0x72,
	.fifo_r_w       = 0x74,
	.raw_gyro       = 0x43,
	.raw_accel      = 0x3B,
	.temp           = 0x41,
	.int_enable     = 0x38,
	//    .dmp_int_status = 0x39,
	.int_status     = 0x3A,
	.accel_intel    = 0x69,
	.pwr_mgmt_1     = 0x6B,
	.pwr_mgmt_2     = 0x6C,
	.int_pin_cfg    = 0x37,
	//    .mem_r_w        = 0x6F,
	.xa_offset      = 0x77,
	.ya_offset      = 0x7A,
	.za_offset      = 0x7D,
	//    .i2c_mst        = 0x24,
	//    .bank_sel       = 0x6D,
	//    .mem_start_addr = 0x6E,
	.prgm_start_h   = 0x70,
	//    .fifo_wm_th     = 0x61,
	.signal_reset   = 0x68,
	//    .st_gyro        = 0x00,
	.st_accel       = 0x0D,
};
#endif
//
#if ICM20690

void ICM20690_read_ID(void)
{
	uint8_t temp_who_am_i,num;
	for (num=0;num<4;num++)
	{
		SPI_master_read_register(ICM20690_reg.who_am_i,1,&temp_who_am_i); 
		if(temp_who_am_i == 0x20) 
		{
			printf("who-am-i = %d,  =0x%02x\r\n",temp_who_am_i,temp_who_am_i);break;
		}
		else if(num==3 && temp_who_am_i != 0x20)
		{
			read_ICM20690_ID = false;
			printf("NO ICM2060x\r\n");
		}
	}	
}


void ICM20690_CHIP_INIT(void)
{
	uint8_t temp;
	temp=0x80;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_1, 1, &temp);		//reset
	delay_ms(100);										    //for chip reset take effect , back to default 0x1
	// 	SPI_master_write_register(reg.prgm_start_h, 1, 0x40);		//disable I2C  only able SPI
	// 	delay_ms(10);
	temp=0x3F;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_2, 1, &temp);	    //disable ACC and GYRO by default.
	delay_ms(10);
	ICM20690_read_ID();
	if (read_ICM20690_ID)
	{
	ICM20690_CHIP_startup();
	}
	else return ;
}

void ICM20690_CHIP_startup(void)
{
	uint8_t temp,ch;
	ICM20690_CHIP_POWERON();
	ICM20690_ACC_POWERON();
	ICM20690_GYRO_POWERON();
	temp=0x27;				//SMPLRT_DIV=9	SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV)	Where INTERNAL_SAMPLE_RATE = 1kHz
	SPI_master_write_register(0x19, 1, &temp);		//ODR设置为25HZ	
	temp=0x05;				//Gro  3db BW,截止频率10HZ
	SPI_master_write_register(0x1a, 1, &temp);		//Gro滤波器设置
	SPI_master_read_register(0x1b,1,&ch);			//读取gro配置
	ch &= 0xE4;				//250dps
	SPI_master_write_register(0x1b, 1,&ch);			//陀螺量程设置	
	temp=0x18;				//[4:3]		±2g (00), ±4g (01), ±8g (10), ±16g (11)
	SPI_master_write_register(0x1c, 1, &temp);		//加表量程设置
	temp=0x05;				//Acc  BW=10HZ
	SPI_master_write_register(0x1d, 1, &temp);		//Acc滤波器设置
	temp=0x00;
	SPI_master_write_register(0x1e, 1, &temp);		//关闭低功耗模式,
	temp=0x00;
	SPI_master_write_register(0x69, 1, &temp);		//Acc Wake-on-Motion设置 ---disable
	delay_ms(10);
}

void ICM20690_CHIP_POWERON(void)
{
	uint8_t temp;
	temp=0x01;	//achieve full gyroscope performance
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_1, 1, &temp);      //00000001 PWR_MGMT_1 [6]SLEEP	When set to 1, the chip is set to sleep mode.
	//[2:0]	CLKSEL[2:0] 1	Auto selects the best available clock source  PLL if ready, else use the Internal oscillator
	delay_ms(10);              //for entering sleep take effect
}
void ICM20690_CHIP_POWEROFF(void)
{
	uint8_t temp;
	temp=0x41;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_1, 1, &temp);      //00000001 PWR_MGMT_1       [6]	SLEEP	When set to 1, the chip is set to sleep mode.
	//                          [2:0]	CLKSEL[2:0] 1	Auto selects the best available clock source  PLL if ready, else use the Internal oscillator
	delay_ms(10);                  //for exiting sleep take effect
}

void ICM20690_ACC_POWERON(void)
{
	uint8_t ch;
	SPI_master_read_register(ICM20690_reg.pwr_mgmt_2,1,&ch);
	ch &= 0xC7;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_2, 1,&ch);        //set [5:3] as 0; 1  XYZ accelerometer is disabled. 0  XYZ accelerometer is on.
}
void ICM20690_ACC_POWEROFF(void)
{
	uint8_t ch;
	SPI_master_read_register(ICM20690_reg.pwr_mgmt_2,1,&ch);
	ch |= 0x38;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_2, 1,&ch);        //set [5:3] as 0; 1  XYZ accelerometer is disabled. 0  XYZ accelerometer is on.
}

void ICM20690_GYRO_POWERON(void)
{
	uint8_t ch;
	SPI_master_read_register(ICM20690_reg.pwr_mgmt_1,1,&ch);	//set gyro clk
	ch |=0x01;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_1, 1,&ch);
	delay_ms(1);

	SPI_master_read_register(ICM20690_reg.pwr_mgmt_2,1,&ch);
	ch &= 0xF8;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_2, 1,&ch);        //set [2:0] as 0; 1  XYZ gyroscope is disabled. 0  XYZ gyroscope is on.
	delay_ms(80);                 //for Start up of the gyro
}
void ICM20690_GYRO_POWEROFF(void)
{
	uint8_t ch;
	SPI_master_read_register(ICM20690_reg.pwr_mgmt_1,1,&ch);	//set gyro clk
	ch &= 0xFE;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_1, 1,&ch);
	delay_ms(1);

	//??? need to double check here whether UI or OIS is still using GYRO , don't do following untill no one use gyro anymore
	SPI_master_read_register(ICM20690_reg.pwr_mgmt_2, 1, &ch);
	ch = 0x80 | 0x07;
	SPI_master_write_register(ICM20690_reg.pwr_mgmt_2, 1, &ch);        //set [2:0] as 0; 1  XYZ gyroscope is disabled. 0  XYZ gyroscope is on.
	delay_ms(200);                 //for discharge
}

void ICM20690_ACC_ENABLE(void)
{
	uint8_t temp;
	temp=0x01;
	//量程,8g
	SPI_master_write_register(ICM20690_reg.accel_cfg, 1, &temp);//00010000 ACCEL_CONFIG [4:3]	AFS_SEL[1:0]	UI Path Accel Full Scale Select:10 = ∮8g
	//量程,16g
	//  write_1B(reg.accel_cfg,0x18);
	//速度,200Hz
	temp=0x04;
	SPI_master_write_register(ICM20690_reg.rate_div, 1, &temp);//00000100 SMPLRT_DIV SMPLRT_DIV[7:0]   200Hz = Divides the internal sample rate (see register CONFIG) to generate the sample rate that controls sensor data output rate, FIFO sample rate.  NOTE: This register is only effective when FCHOICE_B register bits are 2ˇb00, and (0 < DLPF_CFG < 7). This is the update rate of the sensor register: SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV) Where INTERNAL_SAMPLE_RATE = 1kHz
	//滤波器截止频率和噪声带宽
	temp=0x02;
	SPI_master_write_register(ICM20690_reg.accel_cfg2, 1,  &temp);//00100000 ACCEL_CONFIG2       [5:4]  DEC2_CFG[1:0] 0
	//                          [3]    ACCEL_FCHOICE_B    Used to bypass DLPF as shown in the table below
	//                          [2:0]    A_DLPF_CFG    100Hz Bend Pass UI path accelerometer low pass filter setting as shown in the table below  0 ODR 1/(1+SMPLRT_DIV)  : Filter BW 218(Hz)    Filter Delay 1.88(ms)
}
void ICM20690_GYRO_ENABLE(void)
{
	uint8_t  temp;
	//量程,2000dps
	temp=0x0c;
	SPI_master_write_register(ICM20690_reg.gyro_cfg, 1, &temp);//00001100 GYROSCOPE CONFIGURATION [4:2] UI Path Gyro Full Scale Select 011 = ∮2000dps
	//滤波器截止频率和噪声带宽
	temp=0x01;
	SPI_master_write_register(ICM20690_reg.lpf, 1, &temp);//00000001 CONFIGURATION [2:0]	DLPF_CFG[2:0] Filter BW 184(Hz) Filter Delay 2.9 (ms)
	//速度
	temp=0x04;
	SPI_master_write_register(ICM20690_reg.rate_div, 1, &temp);//00000100 SMPLRT_DIV SMPLRT_DIV[7:0]   200Hz = Divides the internal sample rate (see register CONFIG) to generate the sample rate that controls sensor data output rate, FIFO sample rate.  NOTE: This register is only effective when FCHOICE_B register bits are 2ˇb00, and (0 < DLPF_CFG < 7). This is the update rate of the sensor register: SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV) Where INTERNAL_SAMPLE_RATE = 1kHz
	//是否配置Gyro低功耗模式
	temp=0x00;
	SPI_master_write_register(ICM20690_reg.lp_mode_cfg, 1, &temp);//00000000 LP_MODE_CONFIG [7]	GYRO_CYCLE	When set to ˉ1ˇ low-power gyroscope mode is enabled.  Default setting is ˉ0ˇ
}

// void ICM2060x_SET_ACC_GYRO_ODR(uint32_t HZ)  //will only apply on the UI side ACC and GYRO at the same time output
// {
// 	if(HZ > 1024) return;
// 	if(HZ <= 4) return;
// 	SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV)
// 	Where INTERNAL_SAMPLE_RATE = 1kHz
// 	float SMPLRT_DIV_f = 1024.0f/HZ - 1;
// 	uint8_t SMPLRT_DIV = (SMPLRT_DIV_f-(int)SMPLRT_DIV_f)>0.5? ((uint8_t)SMPLRT_DIV_f+1):((uint8_t)SMPLRT_DIV_f);
// 	SPI_master_write_register(reg.rate_div, 1, &SMPLRT_DIV);
// }

void ICM20690_GetACC(void)
{
	uint8_t buf[6]={0};
	uint8_t temp,value1,value2;
	char p,Symbol_1='-',Symbol_2=' ';
	int16_t acc[3]={0};
	float value;
	SPI_master_read_register(ICM20690_reg.raw_accel,6,&buf);
	acc[0] = (int16_t)(((int16_t)buf[0]) << 8 | buf[1]);		//x
	acc[1] = (int16_t)(((int16_t)buf[2]) << 8 | buf[3]);		//y
	acc[2] = (int16_t)(((int16_t)buf[4]) << 8 | buf[5]);		//z
// 		acc[0] = buf[0] << 8 | buf[1];		//x
// 		acc[1] = buf[2] << 8 | buf[3];		//y
// 		acc[2] = buf[4] << 8 | buf[5];		//z
// 	value = (float)acc[0]*9.8f/2048;
// 	value1= (int)value;
// 	value2= (int)((value-value1)*1000)%1000;
// 	printf("acc[0]=%d.%d\r\n",value1,value2);
// 	value = (float)acc[1]*9.8f/2048;
// 	value1= (int)value;
// 	value2= (int)((value-value1)*1000)%1000;
// 	printf("acc[1]=%d.%d\r\n",value1,value2);
// 	if (acc[2] & 0x8000 ==0)
// 	{
// 		p=Symbol_1;
// 	}
// 	else p=Symbol_2;
	//printf("%x\r\n",acc[2]);
// 	value = (float)acc[2]*9.8f/2048;
// 	value1= (int)value;
// 	value2= (int)((value-value1)*1000)%1000;
// 	printf("acc[2]=%d.%d\r\n",value1,value2);
	printf("ACC,%d,%d,%d\r\n",acc[0],acc[1],acc[2]);
}

void ICM20690_GetGYRO(void)
{
	uint8_t buf[6]={0};
	int16_t gry[3]={0};
	SPI_master_read_register(ICM20690_reg.raw_gyro,6,&buf);
	gry[0] = (int16_t)(((int16_t)buf[0]) << 8 | buf[1]);
	gry[1] = (int16_t)(((int16_t)buf[2]) << 8 | buf[3]);
	gry[2] = (int16_t)(((int16_t)buf[4]) << 8 | buf[5]);
	printf("Gro,%d,%d,%d\r\n",gry[0],gry[1],gry[2]);
}


void sensor_dump(void)
{
	uint8_t temp;
	uint8_t value;
	for(temp = 0x0d;temp <= 0x7e;temp++)
	{
		value = 0;
		SPI_master_read_register(temp,1,&value);
		printf("read[%3d] = %3d,read[0x%02x] = 0x%02x\r\n",temp,value,temp,value);
	}
}

#endif

 


 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【MEMS传感器】ICM20690六轴传感器SPI驱动 的相关文章

随机推荐