ICM20948 DMP代码详解(16)
接前一篇文章:ICM20948 DMP代码详解(15)
上一回讲到了inv_icm20948_initialize函数中的inv_icm20948_initialize_lower_driver函数中的inv_icm20948_read_mems_reg函数中的inv_icm20948_set_chip_power_state函数。再次贴出该函数源码:
/*!******************************************************************************* @brief This function sets the power state of the Ivory chip * loop* @param[in] Function - CHIP_AWAKE, CHIP_LP_ENABLE* @param[in] On/Off - The functions are enabled if previously disabled and disabled if previously enabled based on the value of On/Off.*******************************************************************************/
int inv_icm20948_set_chip_power_state(struct inv_icm20948 *s, unsigned char func, unsigned char on_off)
{int status = 0;switch(func) {case CHIP_AWAKE: if(on_off){if((s->base_state.wake_state & CHIP_AWAKE) == 0) {// undo sleep_ens->base_state.pwr_mgmt_1 &= ~BIT_SLEEP;status = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);s->base_state.wake_state |= CHIP_AWAKE;inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds}} else {if(s->base_state.wake_state & CHIP_AWAKE) {// set sleep_ens->base_state.pwr_mgmt_1 |= BIT_SLEEP;status = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);s->base_state.wake_state &= ~CHIP_AWAKE;inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds}}break;case CHIP_LP_ENABLE:if(s->base_state.lp_en_support == 1) {if(on_off) {if( (inv_icm20948_get_lpen_control(s)) && ((s->base_state.wake_state & CHIP_LP_ENABLE) == 0)){s->base_state.pwr_mgmt_1 |= BIT_LP_EN; // lp_en ONstatus = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);s->base_state.wake_state |= CHIP_LP_ENABLE;}} else {if(s->base_state.wake_state & CHIP_LP_ENABLE){s->base_state.pwr_mgmt_1 &= ~BIT_LP_EN; // lp_en offstatus = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);s->base_state.wake_state &= ~CHIP_LP_ENABLE;inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds}}}break;default:break;}// end switchreturn status;
}
上一回说其中还有3个函数需要解析,本回就来一一进行解析。
1)inv_icm20948_write_single_mems_reg_core函数
inv_icm20948_write_single_mems_reg_core函数在C:\Users\ns\Ykq\eMD-SmartMotion-ICM20948-1.1.1\EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Transport.c中,代码如下:
/**
* @brief Write single byte of data to a register on MEMs with no power control
* @param[in] Register address
* @param[in] Data to be written
* @return 0 if successful.
*/
int inv_icm20948_write_single_mems_reg_core(struct inv_icm20948 *s, uint16_t reg, const uint8_t data)
{int result = 0;unsigned char regOnly = (unsigned char)(reg & 0x7F);result |= inv_set_bank(s, reg >> 7);result |= inv_icm20948_write_reg(s, regOnly, &data, 1);return result;
}
函数的功能是在没有电源控制的情况下,将单字节数据写入MEMs上的寄存器。实际上分为两步,先设置bank,后写bank中的寄存器。
inv_set_bank函数也在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Transport.c中,代码如下:
/**
* @brief Set up the register bank register for accessing registers in 20630.
* @param[in] register bank number
* @return 0 if successful.
*/static int inv_set_bank(struct inv_icm20948 *s, unsigned char bank)
{int result;//if bank reg was set before, just returnif(bank==s->lastBank) return 0;else s->lastBank = bank;result = inv_icm20948_read_reg(s, REG_BANK_SEL, &s->reg, 1);if (result)return result;s->reg &= 0xce;s->reg |= (bank << 4);result = inv_icm20948_write_reg(s, REG_BANK_SEL, &s->reg, 1);return result;
}
其实还是通用的先读后写流程。先读取REG_BANK_SEL的内容,设置相关位,再写回去。
REG_BANK_SEL宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中定义,如下:
/* register for all banks */
#define REG_BANK_SEL 0x7F
对应于ICM20948芯片手册中的:
bit5:4正好对应的就是上边代码中的
s->reg &= 0xce;s->reg |= (bank << 4);
inv_icm20948_write_reg函数在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Transport.c中,代码如下:
int inv_icm20948_write_reg(struct inv_icm20948 *s, uint8_t reg, const uint8_t *buf, uint32_t len)
{return inv_icm20948_serif_write_reg(&s->serif, reg, buf, len);
}
参考前文书解析的inv_icm20948_read_reg函数的调用流程(ICM20948 DMP代码详解(9)-CSDN博客):
inv_icm20948_read_reg_one函数 --->
inv_icm20948_read_reg函数 --->
inv_icm20948_serif_read_reg函数 --->
idd_io_hal_read_reg函数
inv_icm20948_write_reg函数的调用流程也是类似的。这里也列一下。
inv_icm20948_serif_write_reg函数在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Serif.h中,代码如下:
static inline int inv_icm20948_serif_write_reg(struct inv_icm20948_serif * s,uint8_t reg, const uint8_t * buf, uint32_t len)
{assert(s);if(len > s->max_write)return INV_ERROR_SIZE;if(s->write_reg(s->context, reg, buf, len) != 0)return INV_ERROR_TRANSPORT;return 0;
}
s->wrire_reg对应的就是idd_io_hal_write_reg函数。
idd_io_hal_write_reg函数在EMD-App\src\ICM20948\system.c中,代码如下:
int idd_io_hal_write_reg(void * context, uint8_t reg, const uint8_t * wbuffer, uint32_t wlen){(void)context;
#if SERIF_TYPE_SPIreturn spi_master_transfer_tx(NULL, reg, wbuffer, wlen);
#else /* SERIF_TYPE_I2C */return i2c_master_write_register(I2C_Address, reg, wlen, wbuffer);
#endif
}
和idd_io_hal_read_reg函数一样,idd_io_hal_write_reg函数中调用的i2c_master_write_register函数如果是自己的板子,也是要换成自己平台下的i2c写函数。
本回内容比较多了,余下内容放到下一回继续解析。