ICM20948 DMP代码详解(31)

接前一篇文章:ICM20948 DMP代码详解(30)

本回继续往下解析inv_icm20948_initialize_lower_driver函数的后续代码。为了便于理解和回顾,再次贴出inv_icm20948_initialize_lower_driver函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,如下:

cpp 复制代码
/** Should be called once on power up. Loads DMP3, initializes internal variables needed 
*   for other lower driver functions.
*/
int inv_icm20948_initialize_lower_driver(struct inv_icm20948 *s, enum SMARTSENSOR_SERIAL_INTERFACE type, 
	const uint8_t *dmp3_image, uint32_t dmp3_image_size)
{
	int result = 0;
	static unsigned char data;
	// set static variable
	s->sAllowLpEn = 1;
	s->s_compass_available = 0;
	// ICM20948 do not support the proximity sensor for the moment.
	// s_proximity_available variable is nerver changes
	s->s_proximity_available = 0;
 
	// Set varialbes to default values
	memset(&s->base_state, 0, sizeof(s->base_state));
	s->base_state.pwr_mgmt_1 = BIT_CLK_PLL;
	s->base_state.pwr_mgmt_2 = BIT_PWR_ACCEL_STBY | BIT_PWR_GYRO_STBY | BIT_PWR_PRESSURE_STBY;
	s->base_state.serial_interface = type;
	result |= inv_icm20948_read_mems_reg(s, REG_USER_CTRL, 1, &s->base_state.user_ctrl);
 
	result |= inv_icm20948_wakeup_mems(s);
 
	result |= inv_icm20948_read_mems_reg(s, REG_WHO_AM_I, 1, &data);
 
	/* secondary cycle mode should be set all the time */
	data = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;
 
	// Set default mode to low power mode
	result |= inv_icm20948_set_lowpower_or_highperformance(s, 0);
	
	// Disable Ivory DMP.
	if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI)   
		s->base_state.user_ctrl = BIT_I2C_IF_DIS;
	else
		s->base_state.user_ctrl = 0;
 
	result |= inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);
 
	//Setup Ivory DMP.
	result |= inv_icm20948_load_firmware(s, dmp3_image, dmp3_image_size);
	if(result)
		return result;
	else
		s->base_state.firmware_loaded = 1;
	result |= inv_icm20948_set_dmp_address(s);
	// Turn off all sensors on DMP by default.
	//result |= dmp_set_data_output_control1(0);   // FIXME in DMP, these should be off by default.
	result |= dmp_icm20948_reset_control_registers(s);
	
	// set FIFO watermark to 80% of actual FIFO size
	result |= dmp_icm20948_set_FIFO_watermark(s, 800);
 
	// Enable Interrupts.
	data = 0x2;
	result |= inv_icm20948_write_mems_reg(s, REG_INT_ENABLE, 1, &data); // Enable DMP Interrupt
	data = 0x1;
	result |= inv_icm20948_write_mems_reg(s, REG_INT_ENABLE_2, 1, &data); // Enable FIFO Overflow Interrupt
 
	// TRACKING : To have accelerometers datas and the interrupt without gyro enables.
	data = 0XE4;
	result |= inv_icm20948_write_mems_reg(s, REG_SINGLE_FIFO_PRIORITY_SEL, 1, &data);
 
	// Disable HW temp fix
	inv_icm20948_read_mems_reg(s, REG_HW_FIX_DISABLE,1,&data);
	data |= 0x08;
	inv_icm20948_write_mems_reg(s, REG_HW_FIX_DISABLE,1,&data);
 
	// Setup MEMs properties.
	s->base_state.accel_averaging = 1; //Change this value if higher sensor sample avergaing is required.
	s->base_state.gyro_averaging = 1;  //Change this value if higher sensor sample avergaing is required.
	inv_icm20948_set_gyro_divider(s, FIFO_DIVIDER);       //Initial sampling rate 1125Hz/19+1 = 56Hz.
	inv_icm20948_set_accel_divider(s, FIFO_DIVIDER);      //Initial sampling rate 1125Hz/19+1 = 56Hz.
 
	// Init the sample rate to 56 Hz for BAC,STEPC and B2S
	dmp_icm20948_set_bac_rate(s, DMP_ALGO_FREQ_56);
	dmp_icm20948_set_b2s_rate(s, DMP_ALGO_FREQ_56);
 
	// FIFO Setup.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_CFG, BIT_SINGLE_FIFO_CFG); // FIFO Config. fixme do once? burst write?
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_RST, 0x1f); // Reset all FIFOs.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_RST, 0x1e); // Keep all but Gyro FIFO in reset.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_EN, 0x0); // Slave FIFO turned off.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_EN_2, 0x0); // Hardware FIFO turned off.
    
	s->base_state.lp_en_support = 1;
	
	if(s->base_state.lp_en_support == 1)
		inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);
 
	result |= inv_icm20948_sleep_mems(s);   
        
	return result;
}

当前来到以下代码片段:

cpp 复制代码
	// Setup MEMs properties.
	s->base_state.accel_averaging = 1; //Change this value if higher sensor sample avergaing is required.
	s->base_state.gyro_averaging = 1;  //Change this value if higher sensor sample avergaing is required.
	inv_icm20948_set_gyro_divider(s, FIFO_DIVIDER);       //Initial sampling rate 1125Hz/19+1 = 56Hz.
	inv_icm20948_set_accel_divider(s, FIFO_DIVIDER);      //Initial sampling rate 1125Hz/19+1 = 56Hz.

两个函数分别来看。

  • inv_icm20948_set_gyro_divider函数

inv_icm20948_set_gyro_divider函数在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,代码如下:

cpp 复制代码
int inv_icm20948_set_gyro_divider(struct inv_icm20948 *s, unsigned char div)
{
	s->base_state.gyro_div = div;
	return inv_icm20948_write_mems_reg(s, REG_GYRO_SMPLRT_DIV, 1, &div);
}

REG_GYRO_SMPLRT_DIV宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中,定义如下:

cpp 复制代码
#define REG_GYRO_SMPLRT_DIV     (BANK_2 | 0x00)

对应芯片手册的以下内容:

正如代码注释所说,这段代码的意思是初始化设置陀螺仪的采样分频值即采样率。具体值为:1125Hz/19+1 = 56Hz。同时,设置s->base_state.gyro_div为实参值FIFO_DIVIDER。FIFO_DIVIDER宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中定义,如下:

cpp 复制代码
#define FIFO_DIVIDER 19
  • inv_icm20948_set_accel_divider函数

inv_icm20948_set_accel_divider函数也在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,代码如下:

cpp 复制代码
int inv_icm20948_set_accel_divider(struct inv_icm20948 *s, short div)
{
	unsigned char data[2] = {0};

	s->base_state.accel_div = div;
	data[0] = (unsigned char)(div >> 8);
	data[1] = (unsigned char)(div & 0xff);

	return inv_icm20948_write_mems_reg(s, REG_ACCEL_SMPLRT_DIV_1, 2, data);
}

REG_ACCEL_SMPLRT_DIV_1宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中,定义如下:

cpp 复制代码
#define REG_ACCEL_SMPLRT_DIV_1  (BANK_2 | 0x10)
#define REG_ACCEL_SMPLRT_DIV_2  (BANK_2 | 0x11)

对应芯片手册的以下内容:

正如代码注释所说,这段代码的意思是初始化设置加速度计的采样分频值即采样率。具体值为:1125Hz/19+1 = 56Hz。同时,设置s->base_state.accel_div为实参值FIFO_DIVIDER。

除了以上两个函数外,还设置了struct inv_icm20948 *s成员:

cpp 复制代码
	s->base_state.accel_averaging = 1; //Change this value if higher sensor sample avergaing is required.
	s->base_state.gyro_averaging = 1;  //Change this value if higher sensor sample avergaing is required.

综合来看,这段代码的意思就是设置陀螺仪和加速度计的采样率,同时记录值到相关成员。

下一回继续解析inv_icm20948_initialize_lower_driver函数中的后续代码。

相关推荐
蓝天居士3 个月前
ICM20948 DMP代码详解(34)
icm20948·dmp
蓝天居士3 个月前
ICM20948 DMP代码详解(33)
icm20948·dmp