ICM20948 DMP代码详解(20)

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

本回继续对inv_icm20948_read_mems_reg函数的其余内容进行解析。为了便于理解和回顾,再次贴出inv_icm20948_read_mems_reg函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Transport.c中,如下:

/**
*  @brief      Read data from a register on MEMs.
*  @param[in]  Register address
*  @param[in]  Length of data
*  @param[in]  Data to be written
*  @return     0 if successful.
*/
int inv_icm20948_read_mems_reg(struct inv_icm20948 * s, uint16_t reg, unsigned int length, unsigned char *data)
{
	int result = 0;
	unsigned int bytesRead = 0;
	unsigned char regOnly = (unsigned char)(reg & 0x7F);
	unsigned char i, dat[INV_MAX_SERIAL_READ];
	unsigned char power_state = inv_icm20948_get_chip_power_state(s);
 
	if((power_state & CHIP_AWAKE) == 0)   // Wake up chip since it is asleep
		result = inv_icm20948_set_chip_power_state(s, CHIP_AWAKE, 1);
 
	if(check_reg_access_lp_disable(s, reg))   // Check if register needs LP_EN to be disabled
		result |= inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 0);  //Disable LP_EN
 
	result |= inv_set_bank(s, reg >> 7);
 
	while (bytesRead<length) 
	{
		int thisLen = min(INV_MAX_SERIAL_READ, length-bytesRead);
		if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {
			result |= inv_icm20948_read_reg(s, regOnly+bytesRead, &dat[bytesRead], thisLen);
		} else {
			result |= inv_icm20948_read_reg(s, regOnly+bytesRead, &data[bytesRead],thisLen);
		}
 
		if (result)
			return result;
 
		bytesRead += thisLen;
	}
 
	if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {
		for (i=0; i< length; i++) {
			*data= dat[i];
			data++;
		}
	}
 
	if(check_reg_access_lp_disable(s, reg))    // Check if register needs LP_EN to be enabled  
		result |= inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);  //Enable LP_EN
 
	return result;
}

接下来进入while循环,开始数据的接收。代码片段如下:

	while (bytesRead<length) 
	{
		int thisLen = min(INV_MAX_SERIAL_READ, length-bytesRead);
		if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {
			result |= inv_icm20948_read_reg(s, regOnly+bytesRead, &dat[bytesRead], thisLen);
		} else {
			result |= inv_icm20948_read_reg(s, regOnly+bytesRead, &data[bytesRead],thisLen);
		}
 
		if (result)
			return result;
 
		bytesRead += thisLen;
	}

先讲一下regOnly,它在inv_icm20948_read_mems_reg函数的开头处赋值:

	unsigned char regOnly = (unsigned char)(reg & 0x7F);

代码中是将寄存器和其所属的bank联合起来进行表示的,bit0~6是寄存器,bit7~8代表其所属的bank。这个regOnly表示的就是不带bank、只带寄存器的值。也就是取下图中红色框中的部分:

回到上边while循环。一开始bytesRead的值为0,length的值为1,因此会进入循环。

thisLen为INV_MAX_SERIAL_READ与length-bytesRead(1-0=1)的较小值。INV_MAX_SERIAL_READ宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Transport.h中定义,如下:

/** @brief Max size that can be read across I2C or SPI data lines */
#define INV_MAX_SERIAL_READ 16
/** @brief Max size that can be written across I2C or SPI data lines */
#define INV_MAX_SERIAL_WRITE 16

那么thisLen的值这里就是1。

接下来走I2C的分支:

        else
        {
			result |= inv_icm20948_read_reg(s, regOnly+bytesRead, &data[bytesRead], thisLen);
        }

inv_ivm20948_read_reg函数前边已经讲过多次,在此不赘述。直接看一下传给它的实参:

regOnly+bytesRead就是regOnly;&data[bytesRead]第一次进入循环的时候是&data[0];thisLen的值是1。这句代码的实际意义就是读取USER_CTRL寄存器,读取1个字节,保存到&data[0]。也就是获取USER_CTRL寄存器的内容。

由于只读取1个字节的内容,因此读一次之后就跳出while循环了。

接下来来到以下代码片段:

	if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {
		for (i=0; i< length; i++) {
			*data= dat[i];
			data++;
		}
	}

对于SPI接口来说,还要从dat[]到data[]“倒”一下。笔者不太理解为何要这样做,不过当前是用I2C接口,也不用“深抠”这一块了。

接下来就到最后一段了:

	if(check_reg_access_lp_disable(s, reg))    // Check if register needs LP_EN to be enabled  
		result |= inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);  //Enable LP_EN

check_reg_access_lp_disable函数上一回讲过,对于USER_CTRL寄存器,总是返回1,会执行inv_icm20948_set_chip_power_state函数。这一句代码的意思是恢复置位LP_EN,也即恢复低功耗使能状态。

至此,inv_icm20948_read_mems_reg函数就都解析完了。其功能概括如下:

唤醒芯片;退出低功耗模式;设置(选择)bank;读取指定寄存器数据;恢复低功耗模式。

下一回将回到inv_icm20948_initialize_lower_driver函数中,继续往下解析接下来的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝天居士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值