[求助] 使用lsm6dsl的sensor hub模式驱动lis2mdl输出数据不变问题

wfagly   2022-3-18 09:25 楼主

按照"an5040-LSM6DSL:始终开启的3D 加速度计和3D 陀螺仪.pdf"的磁铁校准示例去配置lis2mdl,并试过在三个寄存器OUT_MAG_RAW_X_L、SENSORHUB1_REG、SENSORHUB13_REG读取三组数据,但是实际的输出并没有什么变化,用磁铁在传感器上方晃动也不变,可以帮我看看是什么情况吗?

试过按照lsm6dsl的官方驱动去驱,代码如下

int32_t LSM6DSL_SensorHub_Init(void)
{
  // 1. 将 80h 写入 FUNC_CFG_ACCESS // 使能对嵌入功能寄存器的访问(A 区)
  // 2. 将 3Ch 写入 SLV0_ADD // LIS2MDL 从设备地址 = 0011110b
  //    使能写操作(rw_0=0)
  // 3. 将 60h 写入 SLV0_SUBADD // 60h 为待写入的 LIS2MDL 寄存器
  // 4. 将 8Ch 写入 DATAWRITE_SRC_MODE_SUB_SLV0 // 8Ch 为写入到 LIS2MDL 的寄存器 60h 的值
  //    以将其配置为 Continue 模式,
  //    ODR = 100 Hz,温度补偿使能

  uint8_t w_data = 0;

  lsm6dsl_sh_cfg_write_t sh_cfg_write;
  sh_cfg_write.slv0_add = 0x3C;
  sh_cfg_write.slv0_subadd = 0x60;
  sh_cfg_write.slv0_data = 0x8C;

  if (lsm6dsl_sh_cfg_write(&sh_cfg_write) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 5. 将 10h 写入 SLAVE0_CONFIG // 将 Aux_sens_on 位设置为不等于 00b
  if (lsm6dsl_sh_num_of_dev_connected_set(LSM6DSL_SLV_0_1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 6. 将 20h 写入 SLAVE1_CONFIG // 使能 write_once 位
  // 7. 将 00h 写入 FUNC_CFG_ACCESS // 禁用对嵌入功能寄存器的访问(A 区)
  if (lsm6dsl_sh_write_mode_set(LSM6DSL_ONLY_FIRST_CYCLE) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 8. 将 04h 写入 CTRL10_C // 使能嵌入功能
  if (lsm6dsl_func_en_set(1) != LSM6DSL_OK) // lsm6dsl_func_en_set lsm6dsl_pedo_sens_set
  {
    return LSM6DSL_ERROR;
  }

  // 9. 将 09h 写入 MASTER_CONFIG // 使能 SDx/SCx 线上的内部上拉
  //    传感器集合(sensor hub)触发信号为 XL 数据准备就绪
  //    使能辅助 I2C 主线
  if (lsm6dsl_sh_pin_mode_set(LSM6DSL_INTERNAL_PULL_UP) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  if (lsm6dsl_sh_master_set(1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 10. 将 80h 写入 CTRL1_XL // 开启加速度计(以获取触发信号)
  if (lsm6dsl_xl_data_rate_set(LSM6DSL_XL_ODR_1k66Hz) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  lsm6dsl_func_src1_t func_src1 = {0};
  func_src1.sensorhub_end_op = 0;
  do
  {
    // 11. 读取 FUNC_SRC1 // 等待传感器集合通信结束
    // 12. 如果 SENSORHUB_END_OP = 0,转到 9
    if (lsm6dsl_read_reg(LSM6DSL_FUNC_SRC1, (uint8_t *)&func_src1, 1) != LSM6DSL_OK)
    {
      return LSM6DSL_ERROR;
    }
  } while (func_src1.sensorhub_end_op == 0);

  // 13. 将 00h 写入 CTRL10_C // 禁用嵌入功能
  w_data = 0;
  if (lsm6dsl_write_reg(LSM6DSL_CTRL10_C, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  // 14. 将 00h 写入 MASTER_CONFIG // 禁用辅助 I2C 主线
  if (lsm6dsl_write_reg(LSM6DSL_MASTER_CONFIG, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  // 15. 将 00h 写入 CTRL1_XL // 关闭加速度计
  if (lsm6dsl_write_reg(LSM6DSL_CTRL1_XL, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 16. 将 80h 写入 FUNC_CFG_ACCESS // 使能对嵌入功能寄存器的访问(A 区)
  //     使能读操作(rw_0=1)
  // 18. 将 68h 写入 SLV0_SUBADD     // 68h 为待读取的第一个 LIS2MDL 输出寄存器
  // 19. 将 06h 写入 SLAVE0_CONFIG   // 无抽取
  //                                 // 连接了 1 个外部传感器
  //                                 // 读取的寄存器数 = 6
  if (lsm6dsl_mem_bank_set(LSM6DSL_BANK_A) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  w_data = 0x3D;
  if (lsm6dsl_write_reg(LSM6DSL_SLV0_ADD, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  w_data = 0x68;
  if (lsm6dsl_write_reg(LSM6DSL_SLV0_SUBADD, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  w_data = 0x06;
  if (lsm6dsl_write_reg(LSM6DSL_SLAVE0_CONFIG, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 20. 将 FFh 写入 MAG_OFFX_H // X 偏移值初始化
  // 21. 将 20h 写入 MAG_OFFX_L // X 偏移值初始化
  // 22. 将 00h 写入 MAG_OFFY_H // Y 偏移值初始化
  // 23. 将 54h 写入 MAG_OFFY_L // Y 偏移值初始化
  // 24. 将 FFh 写入 MAG_OFFZ_H // Z 偏移值初始化
  // 25. 将 B4h 写入 MAG_OFFZ_L // Z 偏移值初始化
  // 26. 将 0Ah 写入 MAG_SI_XX  // XX 软磁参数
  // 27. 将 01h 写入 MAG_SI_XY  // XY 软磁参数
  // 28. 将 00h 写入 MAG_SI_XZ  // XZ 软磁参数
  // 29. 将 01h 写入 MAG_SI_YX  // YX 软磁参数
  // 30. 将 08h 写入 MAG_SI_YY  // YY 软磁参数
  // 31. 将 81h 写入 MAG_SI_YZ  // YZ 软磁参数
  // 32. 将 00h 写入 MAG_SI_ZX  // ZX 软磁参数
  // 33. 将 81h 写入 MAG_SI_ZY  // ZY 软磁参数
  // 34. 将 0Ah 写入 MAG_SI_ZZ  // ZZ 软磁参数
  // 35. 将 00h 写入 FUNC_CFG_ACCESS // 禁用对嵌入功能寄存器的访问(A 区)

  uint8_t mag_off[6] = {0x20, 0xFF, 0x54, 0x00, 0xB4, 0xFF};
  uint8_t mag_si[9] = {0x0A, 0x01, 0x00, 0x01, 0x08, 0x81, 0x00, 0x81, 0x0A};

  if (lsm6dsl_write_reg(LSM6DSL_MAG_OFFX_H, mag_off, 6) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  if (lsm6dsl_write_reg(LSM6DSL_MAG_SI_XX, mag_si, 9) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  if (lsm6dsl_mem_bank_set(LSM6DSL_USER_BANK) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 36. 将 04h 写入 CTRL10_C // 使能嵌入功能
  if (lsm6dsl_func_en_set(1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 37. 将 0Bh 写入 MASTER_CONFIG // 使能 SDx/SCx 线上的内部上拉
  //     传感器集合(sensor hub)触发信号为 XL 数据准备就绪
  //     使能硬磁校准
  //     使能辅助 I2C 主线
  w_data = 0x0B;
  if (lsm6dsl_write_reg(LSM6DSL_MASTER_CONFIG, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  // 38. 将 04h 写入 CTRL9_XL // 使能软磁校准
  w_data = 0x04;
  if (lsm6dsl_write_reg(LSM6DSL_CTRL9_XL, &w_data, 1) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }
  // 39. 将 80h 写入 CTRL1_XL // 开启加速度计(以获取触发信号)
  if (lsm6dsl_xl_data_rate_set(LSM6DSL_XL_ODR_1k66Hz) != LSM6DSL_OK)
  {
    return LSM6DSL_ERROR;
  }

  return LSM6DSL_OK;
}

第二种,使用lsm6dsl的读写寄存器驱动

/**
 * [url=home.php?mod=space&uid=159083]@brief[/url] Configure Demo
 * @param  None
 * @retval COMPONENT_OK
 * @retval COMPONENT_ERROR
 */
uint8_t Demo_Config(void)
{
	uint8_t writeData = 0x80;
	lsm6dsl_func_src1_t readData = {0};
	
	//1.使能对嵌入功能寄存器的访问(A 区)
	lsm6dsl_write_reg(LSM6DSL_FUNC_CFG_ACCESS, &writeData, 1);
	
	//2.LIS2MDL 从设备地址 = 0011110b
	writeData = 0x3cU;
	lsm6dsl_write_reg(LSM6DSL_SLV0_ADD, &writeData, 1);
	
	//3.60h 为待写入的 LIS2MDL 寄存器
	writeData = 0x60;
	lsm6dsl_write_reg(LSM6DSL_SLV0_SUBADD, &writeData, 1);
	
	//4. 8Ch 为写入到 LIS2MDL 的寄存器 60h 的值, Continue 模式 ODR = 100 Hz
	writeData = 0x8c;
	lsm6dsl_write_reg(LSM6DSL_DATAWRITE_SRC_MODE_SUB_SLV0, &writeData, 1);
	
	//5.将 Aux_sens_on 位设置为不等于 00b
	writeData = 0x10;
	lsm6dsl_write_reg(LSM6DSL_SLAVE0_CONFIG, &writeData, 1);
	
	//6.使能 write_once 位
	writeData = 0x20;
	lsm6dsl_write_reg(LSM6DSL_SLAVE1_CONFIG, &writeData, 1);
	
	//7.禁用对嵌入功能寄存器的访问(A 区)
	writeData = 0x00;
	lsm6dsl_write_reg(LSM6DSL_FUNC_CFG_ACCESS, &writeData, 1);
	
	//8.使能嵌入功能
	writeData = 0x04;
	lsm6dsl_write_reg(LSM6DSL_CTRL10_C, &writeData, 1);
	
	do{
		//9.使能 SDx/SCx 线上的内部上拉  传感器集合(sensor hub)触发信号为 XL 数据准备就绪
		writeData = 0x09;
		lsm6dsl_write_reg(LSM6DSL_MASTER_CONFIG, &writeData, 1);
		
		//10.开启加速度计(以获取触发信号)
		writeData = 0x80;
		lsm6dsl_write_reg(LSM6DSL_CTRL1_XL, &writeData, 1);
		
		//11.等待传感器集合通信结束 
		//12.SENSORHUB_END_OP = 0,转到 9
		lsm6dsl_read_reg(LSM6DSL_FUNC_SRC1, (uint8_t *)&readData, 1);
	} while(!readData.sensorhub_end_op);
	
	//13.禁用嵌入功能
	writeData = 0x00;
	lsm6dsl_write_reg(LSM6DSL_CTRL10_C, &writeData, 1);
	
	//14.禁用辅助 I2C 主线
	writeData = 0x00;
	lsm6dsl_write_reg(LSM6DSL_MASTER_CONFIG, &writeData, 1);
	
	//15.关闭加速度计
	writeData = 0x00;
	lsm6dsl_write_reg(LSM6DSL_CTRL1_XL, &writeData, 1);
	
	//16.使能对嵌入功能寄存器的访问(A 区)
	writeData = 0x80;
	lsm6dsl_write_reg(LSM6DSL_FUNC_CFG_ACCESS, &writeData, 1);
	
	//17.LIS2MDL 从设备地址 = 0011110b
	writeData = 0x3dU;
	lsm6dsl_write_reg(LSM6DSL_SLV0_ADD, &writeData, 1);
	
	//18. 68h 为待读取的第一个 LIS2MDL 输出寄存器
	writeData = 0x68;
	lsm6dsl_write_reg(LSM6DSL_SLV0_SUBADD, &writeData, 1);
	
	//19. 无抽取;连接了 1 个外部传感器
	writeData = 0x06;
	lsm6dsl_write_reg(LSM6DSL_SLAVE0_CONFIG, &writeData, 1);
	
	//20~34
	uint8_t mag_off[6] = {0x20, 0xFF, 0x54, 0x00, 0xB4, 0xFF};
	uint8_t mag_si[9] = {0x0A, 0x01, 0x00, 0x01, 0x08, 0x81, 0x00, 0x81, 0x0A};
	lsm6dsl_write_reg(LSM6DSL_MAG_OFFX_L, mag_off, 6);
	lsm6dsl_write_reg(LSM6DSL_MAG_SI_XX, mag_si, 9);
	
	//35.禁用对嵌入功能寄存器的访问(A 区)
	writeData = 0x00;
	lsm6dsl_write_reg(LSM6DSL_FUNC_CFG_ACCESS, &writeData, 1);
	
	//36.使能嵌入功能
	writeData = 0x04;
	lsm6dsl_write_reg(LSM6DSL_CTRL10_C, &writeData, 1);
	
	//37.使能 SDx/SCx 线上的内部上拉
	writeData = 0x0b;
	lsm6dsl_write_reg(LSM6DSL_MASTER_CONFIG, &writeData, 1);
	
	//38.使能软磁校准
	writeData = 0x04;
	lsm6dsl_write_reg(LSM6DSL_CTRL9_XL, &writeData, 1);
	
	//39.开启加速度计(以获取触发信号)
	writeData = 0x80;
	lsm6dsl_write_reg(LSM6DSL_CTRL1_XL, &writeData, 1);
}

并去读取寄存器,但获取到的值并未有变化

	lsm6dsl_read_reg(LSM6DSL_SENSORHUB13_REG, caliMag, 6);
	lsm6dsl_read_reg(LSM6DSL_SENSORHUB1_REG, cali2Mag, 6);
	lsm6dsl_read_reg(LSM6DSL_OUT_MAG_RAW_X_L, rawMag, 6);

也参考官方的"STM32CubeExpansion_MEMS-XT1_V4.4.0"例子,好像对我的工程也没什么帮助

 

回复评论 (12)

现在能确定硬件都工作正常吗?比如lis2mdl单独通过单片机读取是否正常,I2C电阻也都焊了吗?

点赞  2022-3-18 10:03
引用: littleshrimp 发表于 2022-3-18 10:03 现在能确定硬件都工作正常吗?比如lis2mdl单独通过单片机读取是否正常,I2C电阻也都焊了吗?

焊了,试过lsm6dsl和lis2mdl是可以单独工作的

点赞  2022-3-18 10:12
引用: littleshrimp 发表于 2022-3-18 10:03 现在能确定硬件都工作正常吗?比如lis2mdl单独通过单片机读取是否正常,I2C电阻也都焊了吗?

刚才写问题的时候,我想到先初始化lsm6dsl再去启动sensor hub模式,但是好像又没什么变化

点赞  2022-3-18 10:13

先初始化lsm6dsl再用例程的配置,可以获取寄存器里面的磁力数据

点赞  2022-3-18 10:55
引用: wfagly 发表于 2022-3-18 10:13 刚才写问题的时候,我想到先初始化lsm6dsl再去启动sensor hub模式,但是好像又没什么变化

使用lsm6dsl读取lis2mdl的WHO_AM_I寄存器,能不能获得正确的数据?

点赞  2022-3-18 11:07
引用: littleshrimp 发表于 2022-3-18 11:07 使用lsm6dsl读取lis2mdl的WHO_AM_I寄存器,能不能获得正确的数据?

    uint8_t whoamI = 0;
    lsm6dsl_read_lis2mdl_cx(LIS2MDL_ADDR_CHIPID, &whoamI, 1);
    printf("whoamI is %x\r\n", whoamI);

读出来是40,是正确的

点赞  2022-3-18 11:20
引用: wfagly 发表于 2022-3-18 10:55 先初始化lsm6dsl再用例程的配置,可以获取寄存器里面的磁力数据

你说能读到磁力数据,这个数据现在还是不会受磁场影响吗?

点赞  2022-3-18 11:32

磁力计的使能位设置没有?

点赞  2022-3-18 11:44
引用: littleshrimp 发表于 2022-3-18 11:32 你说能读到磁力数据,这个数据现在还是不会受磁场影响吗?

读到的数据是受磁力影响的不过我用MadgwickAHRSupdate算法得到的航向角不准确

点赞  2022-3-18 14:17
引用: dcexpert 发表于 2022-3-18 11:44 磁力计的使能位设置没有?

使能了,开了连续模式

点赞  2022-3-18 14:18
引用: wfagly 发表于 2022-3-18 14:17 读到的数据是受磁力影响的不过我用MadgwickAHRSupdate算法得到的航向角不准确

这么说就是现在读数据已经正常了是吗?
姿态融合你看看8字校准和传感器个轴的方向设置。

点赞  2022-3-18 16:08
引用: littleshrimp 发表于 2022-3-18 16:08 这么说就是现在读数据已经正常了是吗?姿态融合你看看8字校准和传感器个轴的方向设置。

轴的方向在单个驱动的时候已经调好了,现在还在看这个算法需要磁力计、加速度计、陀螺仪的单位是哪个,高斯还是uT,m/s还是什么,rad/s这些

点赞  2022-3-18 17:07
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复