您的位置:首页 > 汽车 > 新车 > ICM20948 DMP代码详解(21)

ICM20948 DMP代码详解(21)

2024/11/14 13:01:30 来源:https://blog.csdn.net/phmatthaus/article/details/142164687  浏览:    关键词:ICM20948 DMP代码详解(21)

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

 

上一回终于解析完了inv_icm20948_read_mems_reg函数,本回回到inv_icm20948_initialize_lower_driver函数中,继续往下解析该函数接下来的内容。为了便于理解和分析,在此贴出inv_icm20948_initialize_lower_driver函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,如下:

/** 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 variables->sAllowLpEn = 1;s->s_compass_available = 0;// ICM20948 do not support the proximity sensor for the moment.// s_proximity_available variable is nerver changess->s_proximity_available = 0;// Set varialbes to default valuesmemset(&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 moderesult |= 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;elses->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;elses->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 sizeresult |= 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 Interruptdata = 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 fixinv_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 B2Sdmp_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;
}

先来看以下代码片段:

	result |= inv_icm20948_read_mems_reg(s, REG_USER_CTRL, 1, &s->base_state.user_ctrl);

前几回就是从这一行代码开始,深入到inv_icm20948_read_mems_reg函数中进行解析的。现在总体再看一下这行代码的作用,实际上就是读取USER_CTRL寄存器的内容,保存到s->base_state.user_ctrl中。当然,inv_icm20948_read_mems_reg函数并不是简单进行读取(简单读取的函数是inv_icm20948_read_reg),而是先唤醒芯片,再禁止低功耗模式,读取完寄存器内容,再恢复低功耗模式。

接下来来到以下一行:

	result |= inv_icm20948_wakeup_mems(s);

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

/** Wakes up DMP3 (SMARTSENSOR).
*/
int inv_icm20948_wakeup_mems(struct inv_icm20948 *s)
{unsigned char data;int result = 0;result = inv_icm20948_set_chip_power_state(s, CHIP_AWAKE, 1);if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {s->base_state.user_ctrl |= BIT_I2C_IF_DIS;inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);  }data = 0x47;	// FIXME, should set up according to sensor/engines enabled.result |= inv_icm20948_write_mems_reg(s, REG_PWR_MGMT_2, 1, &data);if(s->base_state.firmware_loaded == 1) {s->base_state.user_ctrl |= BIT_DMP_EN | BIT_FIFO_EN;result |= inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);  }result |= inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);return result;
}

一头一尾的两段代码

	result = inv_icm20948_set_chip_power_state(s, CHIP_AWAKE, 1);
	result |= inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);

在前文书解析inv_icm20948_read_mems_reg函数的时候已经讲过了,在此不再赘述。只是注意一点,inv_icm20948_wakeup_mems函数中并没有inv_icm20948_read_mems_reg函数中的禁止LP_EN一段代码,不知是遗漏了还是特意没有加。

70fa883fe0bc40d3ab0970b204a65e08.png

重点来看inv_icm20948_wakeup_mems函数中的以下代码片段:

	if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {s->base_state.user_ctrl |= BIT_I2C_IF_DIS;inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);  }data = 0x47;	// FIXME, should set up according to sensor/engines enabled.result |= inv_icm20948_write_mems_reg(s, REG_PWR_MGMT_2, 1, &data);if(s->base_state.firmware_loaded == 1) {s->base_state.user_ctrl |= BIT_DMP_EN | BIT_FIFO_EN;result |= inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);  }

如果接口是SPI,则调用inv_icm20948_write_single_mem_regs将USER_CTRL寄存器的I2C_IF_DIS位置1。对应于芯片手册中的以下内容:

f78b6e1ec72148d78792a4fef59981ef.png

e96c58658d594a20b1eb6f431dbb0c83.png

257f2c65facf4cb2b152c7ce360e1477.png

inv_icm20948_write_single_mems_reg函数与inv_icm20948_read_single_mems_reg函数流程基本一致,在此也不再详细解析。

inv_icm20948_wakeup_mems函数余下的代码,放在下一回中进行解析。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com