接前一篇文章: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_en
s->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_en
s->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 ON
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_LP_ENABLE;
}
} else {
if(s->base_state.wake_state & CHIP_LP_ENABLE){
s->base_state.pwr_mgmt_1 &= ~BIT_LP_EN; // lp_en off
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_LP_ENABLE;
inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds
}
}
}
break;
default:
break;
}// end switch
return 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 return
if(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_SPI
return 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写函数。
本回内容比较多了,余下内容放到下一回继续解析。