接前一篇文章:ICM20948 DMP代码详解(7)
上一回讲解了EMP-App中的入口函数main()中重点关注的第2段代码的后一个函数inv_icm20948_register_aux_compass,讲解了其各个参数,本回对于函数代码进行解析。为了便于理解和回顾,再次贴出函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948AuxCompassAkm.c中,如下:
void inv_icm20948_register_aux_compass(struct inv_icm20948 * s,
enum inv_icm20948_compass_id compass_id, uint8_t compass_i2c_addr)
{
switch(compass_id) {
case INV_ICM20948_COMPASS_ID_AK09911:
s->secondary_state.compass_slave_id = HW_AK09911;
s->secondary_state.compass_chip_addr = compass_i2c_addr;
s->secondary_state.compass_state = INV_ICM20948_COMPASS_INITED;
/* initialise mounting matrix of compass to identity akm9911 */
s->mounting_matrix_secondary_compass[0] = -1;
s->mounting_matrix_secondary_compass[4] = -1;
s->mounting_matrix_secondary_compass[8] = 1;
break;
case INV_ICM20948_COMPASS_ID_AK09912:
s->secondary_state.compass_slave_id = HW_AK09912;
s->secondary_state.compass_chip_addr = compass_i2c_addr;
s->secondary_state.compass_state = INV_ICM20948_COMPASS_INITED;
/* initialise mounting matrix of compass to identity akm9912 */
s->mounting_matrix_secondary_compass[0] = 1;
s->mounting_matrix_secondary_compass[4] = 1;
s->mounting_matrix_secondary_compass[8] = 1;
break;
case INV_ICM20948_COMPASS_ID_AK08963:
s->secondary_state.compass_slave_id = HW_AK8963;
s->secondary_state.compass_chip_addr = compass_i2c_addr;
s->secondary_state.compass_state = INV_ICM20948_COMPASS_INITED;
/* initialise mounting matrix of compass to identity akm8963 */
s->mounting_matrix_secondary_compass[0] = 1;
s->mounting_matrix_secondary_compass[4] = 1;
s->mounting_matrix_secondary_compass[8] = 1;
break;
case INV_ICM20948_COMPASS_ID_AK09916:
s->secondary_state.compass_slave_id = HW_AK09916;
s->secondary_state.compass_chip_addr = compass_i2c_addr;
s->secondary_state.compass_state = INV_ICM20948_COMPASS_INITED;
/* initialise mounting matrix of compass to identity akm9916 */
s->mounting_matrix_secondary_compass[0] = 1;
s->mounting_matrix_secondary_compass[4] = -1;
s->mounting_matrix_secondary_compass[8] = -1;
break;
default:
s->secondary_state.compass_slave_id = 0;
s->secondary_state.compass_chip_addr = 0;
s->secondary_state.compass_state = INV_ICM20948_COMPASS_RESET;
}
}
函数代码其实也比较好理解。根据第2个参数的实际值进行区分,走不同的分支。上一回已经讲过,此处第2个参数对应的实参为INV_ICM20948_COMPASS_ID_AK09916,该参数对应的枚举值为3,实际意义是选择ICM20948片上自带的AK09916磁力计传感器。
在此,就以case INV_ICM20948_COMPASS_ID_AK09916这一分支为例进行解析,其它分支意思是基本一致的。
case INV_ICM20948_COMPASS_ID_AK09916:
s->secondary_state.compass_slave_id = HW_AK09916;
s->secondary_state.compass_chip_addr = compass_i2c_addr;
s->secondary_state.compass_state = INV_ICM20948_COMPASS_INITED;
/* initialise mounting matrix of compass to identity akm9916 */
s->mounting_matrix_secondary_compass[0] = 1;
s->mounting_matrix_secondary_compass[4] = -1;
s->mounting_matrix_secondary_compass[8] = -1;
break;
一句一句来看,先看第一据个:
s->secondary_state.compass_slave_id = HW_AK09916;
s是函数的第1个参数struct inv_icm20948 * s,它的类型struct inv_icm20948前文书讲到过,当时说后续使用的时候再针对于具体成员进行讲解,现在就到了具体讲解的时候了。struct inv_icm20948代码较长,这里只看与secondary_state成员有关的部分,如下:
typedef struct inv_icm20948 {
struct inv_icm20948_serif serif;
……
/* secondary device support */
struct inv_icm20948_secondary_states {
struct inv_icm20948_secondary_reg {
uint16_t addr;
uint16_t reg;
uint16_t ctrl;
uint16_t d0;
} slv_reg[4];
unsigned char sSavedI2cOdr;
/* compass support */
uint8_t compass_sens[3];
long final_matrix[9];
const int16_t *st_upper;
const int16_t *st_lower;
int scale;
uint8_t dmp_on;
uint8_t secondary_resume_compass_state;
uint8_t mode_reg_addr;
int compass_chip_addr;
int compass_slave_id;
inv_icm20948_compass_state_t compass_state;
} secondary_state;
……
} inv_icm20948_t;
第1句代码的意思就是设置struct inv_icm20948对象的secondary_state成员的compass_slave_id为HW_AK09916。
HW_AK09916宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中定义,如下:
// compass chip list
#define HW_AK8963 0x20
#define HW_AK8975 0x21
#define HW_AK8972 0x22
#define HW_AK09911 0x23
#define HW_AK09912 0x24
#define HW_AK09916 0x25
这里这个0x25,具体代表什么意思,笔者暂时没有弄清楚,既不在ICM20948的芯片手册里,也不在AK09916的芯片手册里。姑且权当作是一个列表中的特定值吧。
接下来的一句是:
s->secondary_state.compass_chip_addr = compass_i2c_addr;
这句代码的意思就是设置struct inv_icm20948对象的secondary_state成员的compass_chip_addr为第3个参数uint8_t compass_i2c_addr。上一回已知道,该值为0x0C,代表的是AK09916的从设备地址。
接下来的一句是:
s->secondary_state.compass_state = INV_ICM20948_COMPASS_INITED;
INV_ICM20948_COMPASS_INITED是一个枚举值,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948.h中定义,如下:
/** @brief States for the secondary device
*/
typedef enum inv_icm20948_compass_state
{
INV_ICM20948_COMPASS_RESET = 0,
INV_ICM20948_COMPASS_INITED,
INV_ICM20948_COMPASS_SETUP,
}inv_icm20948_compass_state_t;
这句代码的意思就是设置struct inv_icm20948对象的secondary_state成员的compass_chip_addr为INV_ICM20948_COMPASS_INITED即已初始化状态。
接下来再看后三句代码:
/* initialise mounting matrix of compass to identity akm9916 */
s->mounting_matrix_secondary_compass[0] = 1;
s->mounting_matrix_secondary_compass[4] = -1;
s->mounting_matrix_secondary_compass[8] = -1;
这里只看struct inv_icm20948中与mounting_matrix_secondary_compass成员有关的部分,如下:
typedef struct inv_icm20948 {
struct inv_icm20948_serif serif;
……
/* Icm20948Fifo usage */
signed char mounting_matrix[9];
signed char mounting_matrix_secondary_compass[9];
long soft_iron_matrix[9];
……
} inv_icm20948_t;
mounting_matrix_secondary_compass数组的作用官方代码中并没有给出解释说明,笔者猜测与磁力计芯片的方向可能有关系,或者可能就是AK09916计算时的固定值。
至此,EMP-App中的入口函数main()中重点关注的第2段代码的后一个函数inv_icm20948_register_aux_compass就解析完了。第2段代码也就解析完成了。
下一回继续往下进行解析。