ICM20948 DMP代码详解(46)

news/2024/9/28 16:26:52/

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

 

上一回讲到了inv_icm20948_setup_compass_akm函数中的以下代码片段:

	/* Set compass in power down through I2C SLV for compass */result = inv_icm20948_execute_write_secondary(s, COMPASS_I2C_SLV_WRITE, s->secondary_state.compass_chip_addr, s->secondary_state.mode_reg_addr, DATA_AKM_MODE_PD);if (result)return result;

本会就对于inv_icm20948_execute_write_secondary函数以及其中调用的inv_icm20948_write_secondary函数代码进行解析。

再次贴出inv_icm20948_execute_write_secondary函数代码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948AuxTransport.c中,如下:

int inv_icm20948_execute_write_secondary(struct inv_icm20948 *s, int index, unsigned char addr, int reg, uint8_t v)
{int result = 0;result |= inv_icm20948_write_secondary(s, index, addr, reg, v);result |= inv_icm20948_secondary_enable_i2c(s);inv_icm20948_sleep_us(SECONDARY_INIT_WAIT*1000);result |= inv_icm20948_secondary_disable_i2c(s);result |= inv_icm20948_secondary_stop_channel(s, index);return result;
}

inv_icm20948_write_secondary函数在同文件中,就在inv_icm20948_execute_write_secondary函数的上边,代码如下:

/*
* inv_icm20948_write_secondary(): set secondary registers for writing?.
The chip must be set as bank 3 before calling.
* This is derived from inv_icm20948_write_secondary in linux...
* for now, uses a very simple data struct for the registers
* 
* index gives the mapping to the particular SLVx registers
* addr is the physical address of the device to be accessed
* reg is the device register we wish to access
* len is the number of bytes to be read
* 
*/
int inv_icm20948_write_secondary(struct inv_icm20948 *s, int index, unsigned char addr, unsigned char reg, char v)
{int result = 0;unsigned char data;data = (unsigned char)addr;result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].addr, 1, &data);data = reg;result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].reg, 1, &data);data = v;result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].d0, 1, &data);data = INV_MPU_BIT_SLV_EN | 1;result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].ctrl, 1, &data);return result;
}

可以对比着前文书对于inv_icm20948_read_secondary函数的解析过程来看。

4894ecce0d6048c3abe69e6d59c5afcd.png

7baf817243a14d6dbf220b6faaa08b1e.png

第1段代码如下:

    data = (unsigned char)addr;result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].addr, 1, &data);

data是addr,即AK09916芯片的地址0x0C。注意,此处由于是写,因此并没有INV_MPU_BIT_I2C_READ | addr。

第2行代码中的s->secondary_state.slv_reg[index].addr是在前文书解析的inv_icm20948_init_secondary函数中初始化的(参见https://phmatthaus.blog.csdn.net/article/details/142306413)。

d7de791f173f4566b6fd1f154ab78020.png

注意,此处的index和inv_icm20948_read_secondary函数不同了,对应的实参是在inv_icm20948_setup_compass_akm函数中传入的,为COMPASS_I2C_SLV_WRITE,就是上一回所说的写通道。

/** @brief I2C from secondary device can stand on up to 4 channels. To perform automatic read and feed DMP :
- channel 0 is reserved for compass reading data
- channel 1 is reserved for compass writing one-shot acquisition register
- channel 2 is reserved for als reading data */
#define COMPASS_I2C_SLV_READ		0
#define COMPASS_I2C_SLV_WRITE		1
#define ALS_I2C_SLV					2

也就是此处的index为1,表示通道1,其用于设置指南针(磁力计芯片)的寄存器。

这样,s->secondary_state.slv_reg[index].addr就是s->secondary_state.slv_reg[1].addr,在inv_icm20948_init_secondary函数中赋的值是REG_I2C_SLV1_ADDR。REG_I2C_SLV1_ADDR宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中,定义如下:

#define REG_I2C_SLV0_ADDR       (BANK_3 | 0x03)
#define REG_I2C_SLV0_REG        (BANK_3 | 0x04)
#define REG_I2C_SLV0_CTRL       (BANK_3 | 0x05)
#define REG_I2C_SLV0_DO         (BANK_3 | 0x06)#define REG_I2C_SLV1_ADDR       (BANK_3 | 0x07)
#define REG_I2C_SLV1_REG        (BANK_3 | 0x08)
#define REG_I2C_SLV1_CTRL       (BANK_3 | 0x09)
#define REG_I2C_SLV1_DO         (BANK_3 | 0x0A)#define REG_I2C_SLV2_ADDR       (BANK_3 | 0x0B)
#define REG_I2C_SLV2_REG        (BANK_3 | 0x0C)
#define REG_I2C_SLV2_CTRL       (BANK_3 | 0x0D)
#define REG_I2C_SLV2_DO         (BANK_3 | 0x0E)#define REG_I2C_SLV3_ADDR       (BANK_3 | 0x0F)
#define REG_I2C_SLV3_REG        (BANK_3 | 0x10)
#define REG_I2C_SLV3_CTRL       (BANK_3 | 0x11)
#define REG_I2C_SLV3_DO         (BANK_3 | 0x12)#define REG_I2C_SLV4_CTRL       (BANK_3 | 0x15)

也就是BANK_3 | 0x07 = (3 << 7) | 0x07。

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

7eb7402b757549a6b3cee5da7b8aa8eb.png

286ae7f479904fd3bf2a566476b1e585.png

综上,inv_icm20948_read_secondary函数第1段代码的意思是:向I2C _SLV1_ADDR寄存器写入1个字节数据,该字节内容为0x0C,由于I2C_SLV1_RN位(bit 7)为低,因此代表准备写入数据。实际上就是选通AK09916磁力计芯片,准备写入数据。

inv_icm20948_write_secondary函数余下代码的解析,请看下回。

 


http://www.ppmy.cn/news/1531113.html

相关文章

矩阵求逆的几种方法

1. 定义 对于矩阵的运算中定义了加减法、乘法&#xff08;包含数乘&#xff09;但未定义矩阵除法&#xff0c;可以简单认为矩阵的逆即为矩阵除法。矩阵求逆是线性代数中的一个重要概念&#xff0c;在很多应用领域都有广泛的应用。对于一个给定的方阵 ( A )&#xff0c;如果存在…

安全开发指南

1. 引言 目的与重要性&#xff1a;阐述安全开发的重要性和目标&#xff0c;比如保护用户数据、维护系统稳定性、避免经济损失等。适用范围&#xff1a;明确指南适用的项目类型、团队规模及开发阶段。 2. 安全原则与最佳实践 最小权限原则&#xff1a;确保每个组件或服务仅拥…

js逆向--npm包管理工具切换国内镜像源

js逆向--npm包管理工具切换国内镜像源 在使用npm包管理工具安装js包时&#xff0c;由于官方源下载速度较慢&#xff0c;有时需要切换为国内源&#xff0c;切换命令如下&#xff1a; npm config set registry https://registry.npmmirror.com如何查看目前的源呢&#xff1f; np…

【有啥问啥】大型语言模型的涌现能力(Emergent Abilities):新一代AI的曙光

大型语言模型的涌现能力&#xff08;Emergent Abilities&#xff09;&#xff1a;新一代AI的曙光 随着人工智能技术的飞速发展&#xff0c;大型语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;展现出了令人惊叹的涌现能力。这种能力并非模型规模简单线性…

【传感器技术】【第1章 传感器与检测技术的理论基础,测量系统,测量分类,误差分析,估计和处理】

目录 第1章 传感器与检测技术的理论基础 1.1 测量系统 2&#xff0e;开环测量系统与闭环测量系统 3、 测量概念 1.2 测量分类 1&#xff0e; 直接测量、 间接测量与组合测量 2&#xff0e; 等精度测量与不等精度测量 3&#xff0e; 偏差式测量、 零位式测量与微差式测量…

ADB 安装教程:如何在 Windows、macOS 和 Linux 上安装 Android Debug Bridge

目录 一、ADB 介绍 二、Windows 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 验证 ADB 安装 4. 配置环境变量 5. 验证全局 ADB 使用 三、macOS 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 配置环境变量 4. 验证 ADB 安装 四、Linux 系统安装 ADB 1. 使用包管理器安装…

[Excel VBA]如何使用VBA自动生成图表

在Excel中&#xff0c;图表是可视化数据的重要工具。以下是一个VBA代码示例&#xff0c;帮助你自动生成图表。 1. 代码说明 该代码会根据指定数据范围创建一个柱状图&#xff0c;并设置图表的基本属性。 2. VBA代码 Sub CreateChart()Dim ws As WorksheetDim chartObj As Ch…

【数据结构与算法】LeetCode:栈

文章目录 栈用栈实现队列最小栈 (Hot 100)有效的括号 (Hot 100)字符串解码 (Hot 100)每日温度 (Hot 100) 栈 用栈实现队列 用栈实现队列 class MyQueue { private:stack<int> st_in; // 输入栈&#xff0c;用于压入传入的数据stack<int> st_out; // 输出栈&…