IMU(LSM6DSMTR+LIS2MDLTR)
LSM6DSMTR(陀螺仪)
概述
LSM6DSMTR 是一款3轴加速度计3轴角速度计的陀螺仪
LGA-14 封装 超小体积
电路设计
采用I2C通信,基本上外部电路只用I2C的上拉和电源滤波即可
1号脚接3V3时 I2C地址为:0xD6
(直接或即可无需右移)
2/3号脚可以接其他I2C器件 如磁力计
两个可编程中断 根据情况使用
CubeMX
两个GPIO 开漏上拉最高等级输出
根据需要设定外部中断
设为上升沿 浮空
I2C
这里使用软件I2C 之前封装过集成库 这里不多介绍了
这里重新封装下
头文件和宏定义
#include \"HZ_I2C.h\"#define IMU_IIC_Soft// #define IMU_LSM6DS_IIC_Hard#ifdef IMU_IIC_Soft#define IMU_SDA_GPIOx GPIOA#define IMU_SDA_Pin GPIO_PIN_4#define IMU_SCL_GPIOx GPIOA#define IMU_SCL_Pin GPIO_PIN_5#define IMU_IIC_Delay 0x1#endif // IMU_IIC_Soft#define IMU_LSM6DS_Addr 0xD6
句柄定义
#ifdef IMU_IIC_SoftHZ_I2C_typedef IMU_I2C_h;#endif // IMU_IIC_Soft
初始化I2C
/** * @brief 初始化I2C * @author HZ12138 * @date 2025-07-15 17:50:23 */void IMU_I2C_Init(void){#ifdef IMU_IIC_Soft // 使用软件IIC 绑定地址 // 绑定SDA和SCL到IIC句柄 I2C_Init_Channel(&IMU_I2C_h, IMU_SDA_GPIOx, IMU_SDA_Pin, IMU_SCL_GPIOx, IMU_SCL_Pin, IMU_IIC_Delay); // addr D6#endif // IMU_IIC_Soft}
读寄存器
/** * @brief 读8bits寄存器 * @param reg 寄存器地址 * @return 读取的数据 * @author HZ12138 * @date 2025-07-15 17:49:51 */uint8_t IMU_LSM6DS_I2C_Read_Reg8(uint8_t reg){#ifdef IMU_IIC_Soft return I2C_Read_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg);#endif // IMU_IIC_Soft}
写寄存器
/** * @brief 写8bits寄存器 * @param reg:寄存器地址 8bit * @param data:数据 * @return 状态 0成功 其他失败 * @author HZ12138 * @date 2025-07-15 19:22:28 */uint8_t IMU_LSM6DS_I2C_Write_Reg8(uint8_t reg, uint8_t data){#ifdef IMU_IIC_Soft return I2C_Write_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, data);#endif // IMU_IIC_Soft}
连续读寄存器
/** * @brief I2C连续读寄存器 * @param reg 寄存器地址 * @param len 长度 * @param buf 缓冲区地址 * @author HZ12138 * @date 2025-07-16 17:19:58 */uint8_t IMU_LSM6DS_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf){#ifdef IMU_IIC_Soft return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, len, buf);#endif // IMU_IIC_Soft}
延迟函数(为了兼容rtos这个函数可以外部重定义)
/** * @brief IMU使用的延迟 可以外部重定义 * @param time 时间 ms * @author HZ12138 * @date 2025-07-15 19:56:18 */__weak void IMU_Delay(uint32_t time){ HAL_Delay(time);}
初始化
复位
本函数有两步操作
首先是复位,之后进入高性能模式
需要操作这个寄存器
bit7 写1 内存复位
bit0 写1 软件复位
- bit7 写1 复位
- 延迟15ms以上
- bit0 写1 软件复位
- 延迟15ms以上
#define IMU_LSM6DS_REG_CTRL3_C 0x12 // 控制寄存器3/** * @brief 软件复位LSM6DS * @author HZ12138 * @date 2025-07-15 19:23:26 */void IMU_LSM6DS_ReStart(void){ uint8_t temp; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, 0x80); // 复位 IMU_Delay(20); temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3 // SW_RESET 写1 temp |= 0x01; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp); IMU_Delay(20);}
设置BDU
块数据更新
数据会将高8bit和低8bit分别存在不同寄存器
打开这个选项会让这两数据同时更新
需要操作这个寄存器
bit6 写1
- 读取寄存器
- 写入数据
- 再次读取验证
#define IMU_LSM6DS_REG_CTRL3_C 0x12 // 控制寄存器3/** * @brief 设置BDU(块数据更新) * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-15 20:41:47 */int IMU_LSM6DS_SetBDU(uint8_t flag){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3 // 写入寄存器 if (flag) temp |= 0x40; // bit 6 写1 else temp &= 0xBF; // bit 6 清零 IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp); // 读取验证是否成功 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); if (temp & 0x40) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}
设置加速度计(a)速率
设置加速度计的采样速率
需要修改以下寄存器的bit[7:4]
#define IMU_LSM6DS_REG_CTRL1_XL 0x10 // 控制寄存器1/* 加速度/角速度 速率选项 */#define IMU_LSM6DS_w_a_RATE_PowerDown 0x00#define IMU_LSM6DS_w_a_RATE_1Hz6 0xB0#define IMU_LSM6DS_w_a_RATE_12Hz5 0x10#define IMU_LSM6DS_w_a_RATE_26Hz 0x20#define IMU_LSM6DS_w_a_RATE_52Hz6 0x30#define IMU_LSM6DS_w_a_RATE_104Hz6 0x40#define IMU_LSM6DS_w_a_RATE_208Hz6 0x50#define IMU_LSM6DS_w_a_RATE_416Hz6 0x60#define IMU_LSM6DS_w_a_RATE_833Hz6 0x70#define IMU_LSM6DS_w_a_RATE_1KHz66 0x80#define IMU_LSM6DS_w_a_RATE_3KHz33 0x90#define IMU_LSM6DS_w_a_RATE_6KHz66 0xA0
/** * @brief 设置加速度(a)速率 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 09:47:25 */int IMU_LSM6DS_Set_a_Rate(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1 // 高4位清零后 写入OPT数据 temp &= 0x0f; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); if ((temp & 0xf0) != opt) return -1; return 0;}
设置角速度计(w)速率
设置加速度计的采样速率
需要修改以下寄存器的bit[7:4]
#define IMU_LSM6DS_REG_CTRL2_G 0x11 // 控制寄存器2/* 加速度/角速度 速率选项 */#define IMU_LSM6DS_w_a_RATE_PowerDown 0x00#define IMU_LSM6DS_w_a_RATE_1Hz6 0xB0#define IMU_LSM6DS_w_a_RATE_12Hz5 0x10#define IMU_LSM6DS_w_a_RATE_26Hz 0x20#define IMU_LSM6DS_w_a_RATE_52Hz6 0x30#define IMU_LSM6DS_w_a_RATE_104Hz6 0x40#define IMU_LSM6DS_w_a_RATE_208Hz6 0x50#define IMU_LSM6DS_w_a_RATE_416Hz6 0x60#define IMU_LSM6DS_w_a_RATE_833Hz6 0x70#define IMU_LSM6DS_w_a_RATE_1KHz66 0x80#define IMU_LSM6DS_w_a_RATE_3KHz33 0x90#define IMU_LSM6DS_w_a_RATE_6KHz66 0xA0
/** * @brief 设置角速度(w)速率 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 10:15:05 */int IMU_LSM6DS_Set_w_rate(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2 // 高4位清零后 写入OPT数据 temp &= 0x0f; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); if ((temp & 0xf0) != opt) return -1; return 0;}
设置加速度计(a)量程
修改以下寄存器的bit[3:2]
#define IMU_LSM6DS_REG_CTRL1_XL 0x10 // 控制寄存器1/*加速度 量程选项*/#define IMU_LSM6DS_a_Full_2g 0x00#define IMU_LSM6DS_a_Full_4g 0x08#define IMU_LSM6DS_a_Full_8g 0x0C#define IMU_LSM6DS_a_Full_16g 0x04
/** * @brief 设置加速度(a)量程 * @param opt 设置选项(IMU_LSM6DS_a_Full_2g/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 10:40:04 */int IMU_LSM6DS_Set_a_Full(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1 // bit 2 3清零后写入opt temp &= 0xF3; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); if ((temp & 0x0C) != opt) return -1; IMU_LSM6DS_a_Full = opt; // 保存参数 return 0;}
注意这里要把参数保存下来以便后面计算数据时使用
设置角速度计(w)量程
修改以下寄存器的bit[3:1]
#define IMU_LSM6DS_REG_CTRL2_G 0x11 // 控制寄存器2/*角速度 量程选项*/#define IMU_LSM6DS_w_Full_125dps 0x02#define IMU_LSM6DS_w_Full_245dps 0x00#define IMU_LSM6DS_w_Full_500dps 0x04#define IMU_LSM6DS_w_Full_1000dps 0x08#define IMU_LSM6DS_w_Full_2000dps 0x0C
/** * @brief 设置角速度(w)量程 * @param opt 设置选项(IMU_LSM6DS_w_Full_125dps/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 10:57:25 */int IMU_LSM6DS_Set_w_Full(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2 // bit 1 2 3 清零后写入opt temp &= 0xf1; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); if ((temp & 0x0E) != opt) return -1; IMU_LSM6DS_w_Full = opt; // 保存参数 return 0;}
注意这里要把参数保存下来以便后面计算数据时使用
设置加速度计带宽
修改以下寄存器的bit0
建议采样率>1.67KHz时选 1.5KHz 其余选400Hz
#define IMU_LSM6DS_REG_CTRL1_XL 0x10 // 控制寄存器1/* 加速度带宽 选项*/#define IMU_LSM6DS_a_BW_1KHz5 0x00#define IMU_LSM6DS_a_BW_400Hz 0x01
/** * @brief 设置加速度计带宽 建议采样率>1.67KHz时选 1.5KHz 其余选400Hz * @param opt 设置选项(IMU_LSM6DS_a_BW_1KHz5/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 12:58:04 */int IMU_LSM6DS_Set_a_BW(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1 // bit 0清零后写入opt temp &= 0xFE; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); if ((temp & 0x01) != opt) return -1; return 0;}
设置加速度计低通滤波
设置以下寄存器以设置加速度计低通滤波
#define IMU_LSM6DS_REG_CTRL8_XL 0x17 // 控制寄存器8/* 加速度计低通滤波 选项 */#define IMU_LSM6DS_a_LOW_PASS_ODR_9 0xC8#define IMU_LSM6DS_a_LOW_PASS_ODR_50 0x88#define IMU_LSM6DS_a_LOW_PASS_ODR_100 0xA8#define IMU_LSM6DS_a_LOW_PASS_ODR_400 0xE8
/** * @brief 设置加速度计低通滤波 * @param opt 设置选项(IMU_LSM6DS_a_LOW_PASS_ODR_9/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 13:47:23 */int IMU_LSM6DS_Set_a_LowPass(uint8_t opt){ uint8_t temp; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL8_XL, opt); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL8_XL); if (temp != opt) return -1; return 0;}
设置角速度计高通滤波
设置以下寄存器
bit6 写1启动角速度计高通滤波
bit[5:4] 设置截止频率
#define IMU_LSM6DS_REG_CTRL7_G 0x16 // 控制寄存器7/*角速度计 高通滤波器 选项 */#define IMU_LSM6DS_w_HP_DISABLE 0x00#define IMU_LSM6DS_w_HP_ENABLE 0x40/*角速度计 高通滤波器截止频率 选项 */#define IMU_LSM6DS_w_HPM_16MHz 0x00#define IMU_LSM6DS_w_HPM_65MHz 0x10#define IMU_LSM6DS_w_HPM_260MHz 0x20#define IMU_LSM6DS_w_HPM_1Hz04 0x30
/** * @brief 设置角速度计高通滤波 * @param en 启用/禁用 (IMU_LSM6DS_w_HP_ENABLE/IMU_LSM6DS_w_HP_DISABLE) * @param opt 设置选项(IMU_LSM6DS_w_HPM_16MHz/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 15:34:18 */int IMU_LSM6DS_Set_w_HighPass(uint8_t en, uint8_t opt){ uint8_t temp; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL7_G, en | opt); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL7_G); if (temp != (en | opt)) return -1; return 0;}
设置角速度计低通滤波带宽
设置bit[1:0]来设置低通滤波带宽
#define IMU_LSM6DS_REG_CTRL6_C 0x15 // 控制寄存器6/*角速度计 低通滤波带宽 选项 */#define IMU_LSM6DS_w_CTRL6_C_FTYPE_1 0x00#define IMU_LSM6DS_w_CTRL6_C_FTYPE_2 0x01#define IMU_LSM6DS_w_CTRL6_C_FTYPE_3 0x02#define IMU_LSM6DS_w_CTRL6_C_FTYPE_4 0x03
/** * @brief 设置角速度计低通滤波带宽 * @param en 0关 1开 * @param opt 设置选项(IMU_LSM6DS_w_CTRL6_C_FTYPE_1/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 15:53:05 */int IMU_LSM6DS_Set_w_LowPassBW(uint8_t en, uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C); // 读取控制寄存器6 // 清除后2位 写入参数 temp &= 0xFC; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL6_C, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C); if ((temp & 0x03) != opt) return -1; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C); // 读取控制寄存器4 // 清除 bit 1 写入参数 temp &= 0xFD; if (en) temp |= 0x02; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL4_C, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C); if (temp & 0x02) { if (!en) // 读取的是1 期望的是0 return -2; } else { if (en) // 读取的是0 期望的是1 return -2; } return 0;}
进入总线直通模式
直通功能示意图
bit2 写入1启用
#define IMU_LSM6DS_REG_MASTER_CONFIG 0x1A // 主机配置寄存器
/** * @brief 进入总线直通模式 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-20 18:41:30 */int IMU_LSM6DS_Enter_Pass_mood(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG); // 读取主机配置寄存器 // bit 2 置1 temp |= 0x04; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG); if (temp & 0x04) return 0; return -1;}
设置中断1
中断设置为脉冲模式,当加速度计和角速度计数据就位后触发中断
以下寄存器的bit[1:0]=11b 设置加速度计和角速度计数据就位后触发中断
以下寄存器bit7写1 启用脉冲模式
#define IMU_LSM6DS_REG_INT1_CTRL 0x0D // IN1 控制寄存器#define IMU_LSM6DS_REG_DRDY_PULSE_CFG 0x0B // 数据就绪寄存器
/** * @brief 设置中断1 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-21 22:27:32 */int IMU_LSM6DS_Set_Int1(void){ uint8_t temp; // 设置数据a,w更新中断 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL); // 读取中断控制寄存器 temp |= 0x03; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_INT1_CTRL, temp); // 写入数据 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL); if ((temp & 0x03) != 0x03) return -1; // 脉冲模式 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG); temp |= 0x80; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG, temp); // 写入数据 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG); if (!(temp & 0x80)) return -1; return 0;}
初始化
/** * @brief LSM6DS 初始化 * @return 0成功 <0失败 * @exception -1 ID错误 * @author HZ12138 * @date 2025-07-15 17:50:41 */int IMU_LSM6DS_Init(void){ IMU_I2C_Init(); // 初始化IIC if (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测ID return -1; IMU_LSM6DS_ReStart(); // 软复位 if (IMU_LSM6DS_SetBDU(1)) // 设置BDU return -2; if (IMU_LSM6DS_Set_a_Rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置加速度计速率 return -3; if (IMU_LSM6DS_Set_w_rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置角速度计速率 return -4; if (IMU_LSM6DS_Set_a_Full(IMU_LSM6DS_a_Full_8g)) // 设置加速度计量程 return -5; if (IMU_LSM6DS_Set_w_Full(IMU_LSM6DS_w_Full_1000dps)) // 设置角速度计量程 return -6; if (IMU_LSM6DS_Set_a_BW(IMU_LSM6DS_a_BW_400Hz)) // 设置加速度计带宽 return -7; if (IMU_LSM6DS_Set_a_LowPass(IMU_LSM6DS_a_LOW_PASS_ODR_50)) // 设置加速度计低通滤波 return -8; if (IMU_LSM6DS_Set_w_HighPass(IMU_LSM6DS_w_HP_ENABLE, IMU_LSM6DS_w_HPM_260MHz)) // 设置角速度计高通滤波 return -9; if (IMU_LSM6DS_Set_w_LowPassBW(1, IMU_LSM6DS_w_CTRL6_C_FTYPE_1)) // 设置角速度计低通滤波带宽 return -10; if (IMU_LSM6DS_Enter_Pass_mood()) // 进入总线直通模式 return -11; if (IMU_LSM6DS_Set_Int1()) // 设置Int1 return -12; return 0;}
获取数据状态
读取以下寄存器的bit[2:0] 分别获取温度,角速度,加速度的数据状态
#define IMU_LSM6DS_REG_STATUS 0x1E // 数据状态寄存器
/** * @brief 获取数据状态(加速度a) * @return 0 已准备完成 <0 未完成w * @author HZ12138 * @date 2025-07-16 16:38:08 */int8_t IMU_LSM6DS_GetState_a(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS); if (temp & 0x01) return 0; return -1;}/** * @brief 获取数据状态(角速度w) * @return 0 已准备完成 <0 未完成 * @author HZ12138 * @date 2025-07-16 16:41:34 */int8_t IMU_LSM6DS_GetState_w(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS); if (temp & 0x02) return 0; return -1;}/** * @brief 获取数据状态(温度T) * @return 0 已准备完成 <0 未完成 * @author HZ12138 * @date 2025-07-16 16:41:56 */int8_t IMU_LSM6DS_GetState_t(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS); if (temp & 0x04) return 0; return -1;}
获取数据
加速度
x/y/z 的高8bit和低8bit 存在以0x28开始的6个寄存器中
拼接数据后根据量程乘上系数即可
/** * @brief 获取加速度(a) * @param ax x方向加速度(单位mg g是重力加速度) * @param ay y方向加速度(单位mg g是重力加速度) * @param az z方向加速度(单位mg g是重力加速度) * @author HZ12138 * @date 2025-07-16 21:30:13 */int8_t IMU_LSM6DS_Get_a(float *ax, float *ay, float *az){ uint8_t buf[6]; int16_t acc[3]; IMU_LSM6DS_I2C_Read_Len_Reg8(0x28, 6, buf); acc[0] = buf[1] << 8 | buf[0]; acc[1] = buf[3] << 8 | buf[2]; acc[2] = buf[5] << 8 | buf[4]; switch (IMU_LSM6DS_a_Full) { case IMU_LSM6DS_a_Full_2g: *ax = ((float)acc[0] * 0.061f); *ay = ((float)acc[1] * 0.061f); *az = ((float)acc[2] * 0.061f); break; case IMU_LSM6DS_a_Full_4g: *ax = ((float)acc[0] * 0.122f); *ay = ((float)acc[1] * 0.122f); *az = ((float)acc[2] * 0.122f); break; case IMU_LSM6DS_a_Full_8g: *ax = ((float)acc[0] * 0.244f); *ay = ((float)acc[1] * 0.244f); *az = ((float)acc[2] * 0.244f); break; case IMU_LSM6DS_a_Full_16g: *ax = ((float)acc[0] * 0.488f); *ay = ((float)acc[1] * 0.488f); *az = ((float)acc[2] * 0.488f); break; default: return -1; } return 0;}
角速度
x/y/z 的高8bit和低8bit 存在以0x22开始的6个寄存器中
根据量程乘上系数即可
/** * @brief 获取角速度(w) * @param wx x方向角速度(mdps 毫度每秒) * @param wy y方向角速度(mdps 毫度每秒) * @param wz z方向角速度(mdps 毫度每秒) * @return 0 成功 <0失败 * @author HZ12138 * @date 2025-07-17 09:43:45 */int8_t IMU_LSM6DS_Get_w(float *wx, float *wy, float *wz){ uint8_t buf[6]; int16_t gry[3]; IMU_LSM6DS_I2C_Read_Len_Reg8(0x22, 6, buf); gry[0] = buf[1] << 8 | buf[0]; gry[1] = buf[3] << 8 | buf[2]; gry[2] = buf[5] << 8 | buf[4]; switch (IMU_LSM6DS_w_Full) { case IMU_LSM6DS_w_Full_245dps: *wx = ((float)gry[0] * 8.750f); *wy = ((float)gry[1] * 8.750f); *wz = ((float)gry[2] * 8.750f); break; case IMU_LSM6DS_w_Full_500dps: *wx = ((float)gry[0] * 17.50f); *wy = ((float)gry[1] * 17.50f); *wz = ((float)gry[2] * 17.50f); break; case IMU_LSM6DS_w_Full_1000dps: *wx = ((float)gry[0] * 35.00f); *wy = ((float)gry[1] * 35.00f); *wz = ((float)gry[2] * 35.00f); break; case IMU_LSM6DS_w_Full_2000dps: *wx = ((float)gry[0] * 70.00f); *wy = ((float)gry[1] * 70.00f); *wz = ((float)gry[2] * 70.00f); break; default: return -1; } return 0;}
温度
温度存在 0x20和0x21里
经过偏移(没找到为啥,根据例程反推的)
/** * @brief 获取温度 * @return 温度(℃) * @author HZ12138 * @date 2025-07-17 09:50:08 */float IMU_LSM6DS_Get_t(void){ uint8_t buf[2]; int16_t temp; IMU_LSM6DS_I2C_Read_Len_Reg8(0x20, 2, buf); temp = buf[1] << 8 | buf[0]; return (((float)temp / 256.0f) + 25.0f);}
LIS2MDLTR(磁力计)
概述
LIS2MDLTR 是一款地磁计
LGA-12 超小封装
电路设计
将LIS2MDLTR的I2C口接到LSM6DSMTR 的 SDX/SCX 上
LSM6DSMTR 启用总线直通
I2C地址为:
0x3C
(直接 或 即可无需右移)
CubeMX
两个GPIO 开漏上拉最高等级输出
根据需要设定外部中断
设为上升沿 浮空
I2C
这里使用软件I2C 之前封装过集成库 这里不多介绍了
这里重新封装下
头文件和宏定义
#include \"HZ_I2C.h\"#define IMU_IIC_Soft// #define IMU_LSM6DS_IIC_Hard#ifdef IMU_IIC_Soft#define IMU_SDA_GPIOx GPIOA#define IMU_SDA_Pin GPIO_PIN_4#define IMU_SCL_GPIOx GPIOA#define IMU_SCL_Pin GPIO_PIN_5#define IMU_IIC_Delay 0x1#endif // IMU_IIC_Soft#define IMU_LIS2MD_Addr 0x3C
句柄定义
#ifdef IMU_IIC_SoftHZ_I2C_typedef IMU_I2C_h;#endif // IMU_IIC_Soft
初始化I2C
/** * @brief 初始化I2C * @author HZ12138 * @date 2025-07-15 17:50:23 */void IMU_I2C_Init(void){#ifdef IMU_IIC_Soft // 使用软件IIC 绑定地址 // 绑定SDA和SCL到IIC句柄 I2C_Init_Channel(&IMU_I2C_h, IMU_SDA_GPIOx, IMU_SDA_Pin, IMU_SCL_GPIOx, IMU_SCL_Pin, IMU_IIC_Delay); // addr D6#endif // IMU_IIC_Soft}
读寄存器
/** * @brief 读8bits寄存器 * @param reg 寄存器地址 * @return 读取的数据 * @author HZ12138 * @date 2025-07-15 17:49:51 */uint8_t IMU_LIS2MD_I2C_Read_Reg8(uint8_t reg){#ifdef IMU_IIC_Soft return I2C_Read_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg);#endif // IMU_IIC_Soft}
写寄存器
/** * @brief 写8bits寄存器 * @param reg:寄存器地址 8bit * @param data:数据 * @return 状态 0成功 其他失败 * @author HZ12138 * @date 2025-07-15 19:22:28 */uint8_t IMU_LIS2MD_I2C_Write_Reg8(uint8_t reg, uint8_t data){#ifdef IMU_IIC_Soft return I2C_Write_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, data);#endif // IMU_IIC_Soft}
连续读寄存器
/** * @brief I2C连续读寄存器 * @param reg 寄存器地址 * @param len 长度 * @param buf 缓冲区地址 * @author HZ12138 * @date 2025-07-16 17:19:58 */uint8_t IMU_LIS2MD_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf){#ifdef IMU_IIC_Soft return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, len, buf);#endif // IMU_IIC_Soft}
延迟函数(为了兼容rtos这个函数可以外部重定义)
/** * @brief IMU使用的延迟 可以外部重定义 * @param time 时间 ms * @author HZ12138 * @date 2025-07-15 19:56:18 */__weak void IMU_Delay(uint32_t time){ HAL_Delay(time);}
初始化
复位
设置0x60寄存器
bit5 写1 复位
复位后延迟至少15ms
#define IMU_LIS2MD_REG_CFG_A 0x60 // 控制寄存器A
/** * @brief LIS2MD复位 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 13:58:46 */int IMU_LIS2MD_Restart(void){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); temp |= 0x20; if (IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp)) return -1; IMU_Delay(20); return 0;}
设置BDU
块数据更新
数据会将高8bit和低8bit分别存在不同寄存器
打开这个选项会让这两数据同时更新
设置0x62寄存器
bit4 写1 启动
#define IMU_LIS2MD_REG_CFG_C 0x62 // 控制寄存器C
/** * @brief 设置BDU(块数据更新) * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 14:15:28 */int IMU_LIS2MD_Set_BDU(uint8_t flag){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C); // 读取控制寄存器C // 写入寄存器 if (flag) temp |= 0x10; // bit 4 写1 else temp &= 0xEF; // bit 4 清零 IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_C, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C); if (temp & 0x10) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}
读取ID
ID为 0x40
读取0x4F寄存器获取ID
#define IMU_LIS2MD_REG_ID 0x4F // ID寄存器
/** * @brief 读取ID * @return ID * @author HZ12138 * @date 2025-07-18 13:35:33 */uint8_t IMU_LIS2MD_Read_ID(void){ return IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_ID);}
设置输出速率
设置0x60寄存器
设置bit[3:2]设置输出速率
#define IMU_LIS2MD_REG_CFG_A 0x60 // 控制寄存器A/* 数据输出 选项 */#define IMU_LIS2MD_ODR_10Hz 0x00#define IMU_LIS2MD_ODR_20Hz 0x04#define IMU_LIS2MD_ODR_50Hz 0x08#define IMU_LIS2MD_ODR_100Hz 0x0C
/** * @brief 设置输出速率 * @param opt 选项( IMU_LIS2MD_ODR_10Hz /...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 15:35:04 */int IMU_LIS2MD_Set_ODR(uint8_t opt){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); temp |= opt; IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp); temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); if ((temp & 0x0C) != opt) return -1; return 0;}
设置偏移消除
0x61寄存器
bit1 写1启动
#define IMU_LIS2MD_REG_CFG_B 0x61 // 控制寄存器B
/** * @brief 设置偏移消除 * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 16:39:28 */int IMU_LIS2MD_Set_Offset_CANC(uint8_t flag){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B); // 读取控制寄存器B // 写入寄存器 if (flag) temp |= 0x02; // bit 1 写1 else temp &= 0xFD; // bit 1 清零 IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_B, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B); if (temp & 0x02) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}
设置温度补偿
设置0x60寄存器
bit7 写1 启动
#define IMU_LIS2MD_REG_CFG_A 0x60 // 控制寄存器A
/** * @brief 设置温度补偿 * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 16:45:30 */int IMU_LIS2MD_Set_TempComp(uint8_t flag){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A // 写入寄存器 if (flag) temp |= 0x80; // bit 1 写1 else temp &= 0x7F; // bit 1 清零 IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); if (temp & 0x80) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}
设置输出模式
设置0x60寄存器
bit[1:0]设置
#define IMU_LIS2MD_REG_CFG_A 0x60 // 控制寄存器A/* 模式设置 选项 */#define IMU_LIS2MD_MODE_Idle 0x11#define IMU_LIS2MD_MODE_Single 0x01#define IMU_LIS2MD_MODE_Continuous 0x00
/** * @brief 设置模式 * @param opt 选项(IMU_LIS2MD_MODE_Continuous/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 17:10:08 */int IMU_LIS2MD_Set_Mode(uint8_t opt){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A temp &= 0xFC; temp |= opt; IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); if ((temp & 0x03) != opt) return -1; return 0;}
初始化
/** * @brief 初始化LIS2MD * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 13:32:30 */int IMU_LIS2MD_Init(void){ if (IMU_LIS2MD_Read_ID() != 0x40) // 验证ID return -1; if (IMU_LIS2MD_Restart() != 0) // 复位 return -2; if (IMU_LIS2MD_Set_BDU(1) != 0) // 设置块数据更新 return -3; if (IMU_LIS2MD_Set_ODR(IMU_LIS2MD_ODR_50Hz) != 0) // 设置数据更新速率 return -4; if (IMU_LIS2MD_Set_Offset_CANC(1) != 0) // 设置偏移消除 return -5; if (IMU_LIS2MD_Set_TempComp(1) != 0) // 设置温度补偿 return -6; HAL_Delay(10); if (IMU_LIS2MD_Set_Mode(IMU_LIS2MD_MODE_Continuous) != 0) // 启动连续模式 return -7; return 0;}
获取数据状态
读取0x67寄存器
bit3 为1时代表数据准备完成
#define IMU_LIS2MD_REG_STATUS 0x67 // 状态寄存器
/** * @brief 获取数据状态 * @return 0 没有准备好 1 准备完成 * @author HZ12138 * @date 2025-07-18 21:01:46 */uint8_t IMU_LIS2MD_Get_State(void){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_STATUS); // 读取状态寄存器 if (temp & 0x08) return 1; return 0;}
获取磁场数据
x/y/z 的高8bit和低8bit 存在以0x68开始的6个寄存器中
/** * @brief 获取磁场数据 单位 mG(毫高斯) * @param mx x方向磁场 * @param my y方向磁场 * @param mz z方向磁场 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 21:01:44 */int IMU_LIS2MD_Get_Magnetic(float *mx, float *my, float *mz){ uint8_t buf[6]; int16_t temp_mx, temp_my, temp_mz; if (IMU_LIS2MD_I2C_Read_Len_Reg8(0x68, 6, buf)) return -1; temp_mx = (buf[1] << 8) | buf[0]; temp_my = (buf[3] << 8) | buf[2]; temp_mz = (buf[5] << 8) | buf[4]; *mx = (float)temp_mx * 1.5f; *my = (float)temp_my * 1.5f; *mz = (float)temp_mz * 1.5f; return 0;}
获取温度
温度存在0x6E和0x6F寄存器中
/** * @brief 获取温度 * @return 温度 (℃) * @author HZ12138 * @date 2025-07-18 21:20:59 */float IMU_LIS2MD_Get_T(void){ uint8_t buf[2]; int16_t temp; IMU_LIS2MD_I2C_Read_Len_Reg8(0x6E, 2, buf); temp = (buf[1] << 8 | buf[0]); return (((float)temp / 8.0f) + 25.0f);}
文件
IMU_LSM6DS.c
#include \"IMU.h\"uint8_t IMU_LSM6DS_a_Full, IMU_LSM6DS_w_Full;/** * @brief IMU使用的延迟 可以外部重定义 * @param time 时间 ms * @author HZ12138 * @date 2025-07-15 19:56:18 */__weak void IMU_Delay(uint32_t time){ HAL_Delay(time);}/** * @brief 软件复位LSM6DS * @author HZ12138 * @date 2025-07-15 19:23:26 */void IMU_LSM6DS_ReStart(void){ uint8_t temp; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, 0x80); // 复位 IMU_Delay(20); temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3 // SW_RESET 写1 temp |= 0x01; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp); IMU_Delay(20);}/** * @brief 设置BDU(块数据更新) * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-15 20:41:47 */int IMU_LSM6DS_SetBDU(uint8_t flag){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3 // 写入寄存器 if (flag) temp |= 0x40; // bit 6 写1 else temp &= 0xBF; // bit 6 清零 IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp); // 读取验证是否成功 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); if (temp & 0x40) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}/** * @brief 设置加速度(a)速率 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 09:47:25 */int IMU_LSM6DS_Set_a_Rate(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1 // 高4位清零后 写入OPT数据 temp &= 0x0f; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); if ((temp & 0xf0) != opt) return -1; return 0;}/** * @brief 设置角速度(w)速率 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 10:15:05 */int IMU_LSM6DS_Set_w_rate(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2 // 高4位清零后 写入OPT数据 temp &= 0x0f; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); if ((temp & 0xf0) != opt) return -1; return 0;}/** * @brief 设置加速度(a)量程 * @param opt 设置选项(IMU_LSM6DS_a_Full_2g/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 10:40:04 */int IMU_LSM6DS_Set_a_Full(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1 // bit 2 3清零后写入opt temp &= 0xF3; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); if ((temp & 0x0C) != opt) return -1; IMU_LSM6DS_a_Full = opt; // 保存参数 return 0;}/** * @brief 设置角速度(w)量程 * @param opt 设置选项(IMU_LSM6DS_w_Full_125dps/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 10:57:25 */int IMU_LSM6DS_Set_w_Full(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2 // bit 1 2 3 清零后写入opt temp &= 0xf1; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); if ((temp & 0x0E) != opt) return -1; IMU_LSM6DS_w_Full = opt; // 保存参数 return 0;}/** * @brief 设置加速度计带宽 建议采样率>1.67KHz时选 1.5KHz 其余选400Hz * @param opt 设置选项(IMU_LSM6DS_a_BW_1KHz5/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 12:58:04 */int IMU_LSM6DS_Set_a_BW(uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1 // bit 0清零后写入opt temp &= 0xFE; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); if ((temp & 0x01) != opt) return -1; return 0;}/** * @brief 设置加速度计低通滤波 * @param opt 设置选项(IMU_LSM6DS_a_LOW_PASS_ODR_9/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 13:47:23 */int IMU_LSM6DS_Set_a_LowPass(uint8_t opt){ uint8_t temp; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL8_XL, opt); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL8_XL); if (temp != opt) return -1; return 0;}/** * @brief 设置角速度计高通滤波 * @param en 启用/禁用 (IMU_LSM6DS_w_HP_ENABLE/IMU_LSM6DS_w_HP_DISABLE) * @param opt 设置选项(IMU_LSM6DS_w_HPM_16MHz/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 15:34:18 */int IMU_LSM6DS_Set_w_HighPass(uint8_t en, uint8_t opt){ uint8_t temp; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL7_G, en | opt); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL7_G); if (temp != (en | opt)) return -1; return 0;}/** * @brief 设置角速度计低通滤波带宽 * @param en 0关 1开 * @param opt 设置选项(IMU_LSM6DS_w_CTRL6_C_FTYPE_1/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-16 15:53:05 */int IMU_LSM6DS_Set_w_LowPassBW(uint8_t en, uint8_t opt){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C); // 读取控制寄存器6 // 清除后2位 写入参数 temp &= 0xFC; temp |= opt; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL6_C, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C); if ((temp & 0x03) != opt) return -1; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C); // 读取控制寄存器4 // 清除 bit 1 写入参数 temp &= 0xFD; if (en) temp |= 0x02; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL4_C, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C); if (temp & 0x02) { if (!en) // 读取的是1 期望的是0 return -2; } else { if (en) // 读取的是0 期望的是1 return -2; } return 0;}/** * @brief 进入总线直通模式 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-20 18:41:30 */int IMU_LSM6DS_Enter_Pass_mood(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG); // 读取主机配置寄存器 // bit 2 置1 temp |= 0x04; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG, temp); // 写入数据 // 读取后检测 是否正确 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG); if (temp & 0x04) return 0; return -1;}/** * @brief 设置中断1 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-21 22:27:32 */int IMU_LSM6DS_Set_Int1(void){ uint8_t temp; // 设置数据a,w更新中断 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL); // 读取中断控制寄存器 temp |= 0x03; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_INT1_CTRL, temp); // 写入数据 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL); if ((temp & 0x03) != 0x03) return -1; // 脉冲模式 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG); temp |= 0x80; IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG, temp); // 写入数据 temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG); if (!(temp & 0x80)) return -1; return 0;}/** * @brief LSM6DS 初始化 * @return 0成功 <0失败 * @exception -1 ID错误 * @author HZ12138 * @date 2025-07-15 17:50:41 */int IMU_LSM6DS_Init(void){ IMU_I2C_Init(); // 初始化IIC if (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测ID return -1; IMU_LSM6DS_ReStart(); // 软复位 if (IMU_LSM6DS_SetBDU(1)) // 设置BDU return -2; if (IMU_LSM6DS_Set_a_Rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置加速度计速率 return -3; if (IMU_LSM6DS_Set_w_rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置角速度计速率 return -4; if (IMU_LSM6DS_Set_a_Full(IMU_LSM6DS_a_Full_8g)) // 设置加速度计量程 return -5; if (IMU_LSM6DS_Set_w_Full(IMU_LSM6DS_w_Full_1000dps)) // 设置角速度计量程 return -6; if (IMU_LSM6DS_Set_a_BW(IMU_LSM6DS_a_BW_400Hz)) // 设置加速度计带宽 return -7; if (IMU_LSM6DS_Set_a_LowPass(IMU_LSM6DS_a_LOW_PASS_ODR_50)) // 设置加速度计低通滤波 return -8; if (IMU_LSM6DS_Set_w_HighPass(IMU_LSM6DS_w_HP_ENABLE, IMU_LSM6DS_w_HPM_260MHz)) // 设置角速度计高通滤波 return -9; if (IMU_LSM6DS_Set_w_LowPassBW(1, IMU_LSM6DS_w_CTRL6_C_FTYPE_1)) // 设置角速度计低通滤波带宽 return -10; if (IMU_LSM6DS_Enter_Pass_mood()) // 进入总线直通模式 return -11; if (IMU_LSM6DS_Set_Int1()) // 设置Int1 return -12; return 0;}/** * @brief 获取数据状态(加速度a) * @return 0 已准备完成 <0 未完成w * @author HZ12138 * @date 2025-07-16 16:38:08 */int8_t IMU_LSM6DS_GetState_a(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS); if (temp & 0x01) return 0; return -1;}/** * @brief 获取数据状态(角速度w) * @return 0 已准备完成 <0 未完成 * @author HZ12138 * @date 2025-07-16 16:41:34 */int8_t IMU_LSM6DS_GetState_w(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS); if (temp & 0x02) return 0; return -1;}/** * @brief 获取数据状态(温度T) * @return 0 已准备完成 <0 未完成 * @author HZ12138 * @date 2025-07-16 16:41:56 */int8_t IMU_LSM6DS_GetState_t(void){ uint8_t temp; temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS); if (temp & 0x04) return 0; return -1;}/** * @brief 获取加速度(a) * @param ax x方向加速度(单位mg g是重力加速度) * @param ay y方向加速度(单位mg g是重力加速度) * @param az z方向加速度(单位mg g是重力加速度) * @author HZ12138 * @date 2025-07-16 21:30:13 */int8_t IMU_LSM6DS_Get_a(float *ax, float *ay, float *az){ uint8_t buf[6]; int16_t acc[3]; IMU_LSM6DS_I2C_Read_Len_Reg8(0x28, 6, buf); acc[0] = buf[1] << 8 | buf[0]; acc[1] = buf[3] << 8 | buf[2]; acc[2] = buf[5] << 8 | buf[4]; switch (IMU_LSM6DS_a_Full) { case IMU_LSM6DS_a_Full_2g: *ax = ((float)acc[0] * 0.061f); *ay = ((float)acc[1] * 0.061f); *az = ((float)acc[2] * 0.061f); break; case IMU_LSM6DS_a_Full_4g: *ax = ((float)acc[0] * 0.122f); *ay = ((float)acc[1] * 0.122f); *az = ((float)acc[2] * 0.122f); break; case IMU_LSM6DS_a_Full_8g: *ax = ((float)acc[0] * 0.244f); *ay = ((float)acc[1] * 0.244f); *az = ((float)acc[2] * 0.244f); break; case IMU_LSM6DS_a_Full_16g: *ax = ((float)acc[0] * 0.488f); *ay = ((float)acc[1] * 0.488f); *az = ((float)acc[2] * 0.488f); break; default: return -1; } return 0;}/** * @brief 获取角速度(w) * @param wx x方向角速度(mdps 毫度每秒) * @param wy y方向角速度(mdps 毫度每秒) * @param wz z方向角速度(mdps 毫度每秒) * @return 0 成功 <0失败 * @author HZ12138 * @date 2025-07-17 09:43:45 */int8_t IMU_LSM6DS_Get_w(float *wx, float *wy, float *wz){ uint8_t buf[6]; int16_t gry[3]; IMU_LSM6DS_I2C_Read_Len_Reg8(0x22, 6, buf); gry[0] = buf[1] << 8 | buf[0]; gry[1] = buf[3] << 8 | buf[2]; gry[2] = buf[5] << 8 | buf[4]; switch (IMU_LSM6DS_w_Full) { case IMU_LSM6DS_w_Full_245dps: *wx = ((float)gry[0] * 8.750f); *wy = ((float)gry[1] * 8.750f); *wz = ((float)gry[2] * 8.750f); break; case IMU_LSM6DS_w_Full_500dps: *wx = ((float)gry[0] * 17.50f); *wy = ((float)gry[1] * 17.50f); *wz = ((float)gry[2] * 17.50f); break; case IMU_LSM6DS_w_Full_1000dps: *wx = ((float)gry[0] * 35.00f); *wy = ((float)gry[1] * 35.00f); *wz = ((float)gry[2] * 35.00f); break; case IMU_LSM6DS_w_Full_2000dps: *wx = ((float)gry[0] * 70.00f); *wy = ((float)gry[1] * 70.00f); *wz = ((float)gry[2] * 70.00f); break; default: return -1; } return 0;}/** * @brief 获取温度 * @return 温度(℃) * @author HZ12138 * @date 2025-07-17 09:50:08 */float IMU_LSM6DS_Get_t(void){ uint8_t buf[2]; int16_t temp; IMU_LSM6DS_I2C_Read_Len_Reg8(0x20, 2, buf); temp = buf[1] << 8 | buf[0]; return (((float)temp / 256.0f) + 25.0f);}extern char CDC_data[500];/** * @brief 打印所有数据 (ax,ay,az,wx,wy,wz,t) * @author HZ12138 * @date 2025-07-17 09:54:18 */void IMU_LSM6DS_Print_data(void){ float ax, ay, az; float wx, wy, wz; float t; int temp; // if (IMU_LSM6DS_GetState_a() == 0) temp = IMU_LSM6DS_Get_a(&ax, &ay, &az); // if (IMU_LSM6DS_GetState_w() == 0) temp = IMU_LSM6DS_Get_w(&wx, &wy, &wz); // if (IMU_LSM6DS_GetState_t() == 0) // t = IMU_LSM6DS_Get_t(); memset(CDC_data, 0, 500); sprintf(CDC_data, \"%f,%f,%f,%f,%f,%f,%f\\n\", ax, ay, az, wx, wy, wz, t); CDC_Transmit(0, (uint8_t *)CDC_data, strlen(CDC_data)); // printf(\"%f,%f,%f,%f,%f,%f,%f\\n\", ax, ay, az, wx, wy, wz, t);}
IMU_LSM6DS.h
#ifndef _IMU_LSM6DS_H_#define _IMU_LSM6DS_H_#define IMU_LSM6DS_REG_ID 0x0F // ID寄存器#define IMU_LSM6DS_REG_CTRL1_XL 0x10 // 控制寄存器1#define IMU_LSM6DS_REG_CTRL2_G 0x11 // 控制寄存器2#define IMU_LSM6DS_REG_CTRL3_C 0x12 // 控制寄存器3#define IMU_LSM6DS_REG_CTRL4_C 0x13 // 控制寄存器4#define IMU_LSM6DS_REG_CTRL6_C 0x15 // 控制寄存器6#define IMU_LSM6DS_REG_CTRL7_G 0x16 // 控制寄存器7#define IMU_LSM6DS_REG_CTRL8_XL 0x17 // 控制寄存器8#define IMU_LSM6DS_REG_STATUS 0x1E // 数据状态寄存器#define IMU_LSM6DS_REG_MASTER_CONFIG 0x1A // 主机配置寄存器#define IMU_LSM6DS_REG_FIFO_CTRL1 0x06 // FIFO控制寄存器1#define IMU_LSM6DS_REG_FIFO_CTRL2 0x07 // FIFO控制寄存器2#define IMU_LSM6DS_REG_FIFO_CTRL3 0x08 // FIFO控制寄存器3#define IMU_LSM6DS_REG_FIFO_CTRL4 0x09 // FIFO控制寄存器4#define IMU_LSM6DS_REG_FIFO_CTRL5 0x0A // FIFO控制寄存器5#define IMU_LSM6DS_REG_INT1_CTRL 0x0D // IN1 控制寄存器#define IMU_LSM6DS_REG_FIFO_STATUS1 0x3A // FIFO状态寄存器1#define IMU_LSM6DS_REG_FIFO_STATUS2 0x3B // FIFO状态寄存器2#define IMU_LSM6DS_REG_FIFO_STATUS3 0x3C // FIFO状态寄存器3#define IMU_LSM6DS_REG_FIFO_STATUS4 0x3D // FIFO状态寄存器4#define IMU_LSM6DS_REG_FIFO_DATA_OUT_L 0x3E // FIFO数据寄存器L#define IMU_LSM6DS_REG_FIFO_DATA_OUT_H 0x3F // FIFO数据寄存器F#define IMU_LSM6DS_REG_TAP_CFG 0x58 // TAP设置寄存器#define IMU_LSM6DS_REG_DRDY_PULSE_CFG 0x0B // 数据就绪寄存器/* 加速度/角速度 速率选项 */#define IMU_LSM6DS_w_a_RATE_PowerDown 0x00#define IMU_LSM6DS_w_a_RATE_1Hz6 0xB0#define IMU_LSM6DS_w_a_RATE_12Hz5 0x10#define IMU_LSM6DS_w_a_RATE_26Hz 0x20#define IMU_LSM6DS_w_a_RATE_52Hz6 0x30#define IMU_LSM6DS_w_a_RATE_104Hz6 0x40#define IMU_LSM6DS_w_a_RATE_208Hz6 0x50#define IMU_LSM6DS_w_a_RATE_416Hz6 0x60#define IMU_LSM6DS_w_a_RATE_833Hz6 0x70#define IMU_LSM6DS_w_a_RATE_1KHz66 0x80#define IMU_LSM6DS_w_a_RATE_3KHz33 0x90#define IMU_LSM6DS_w_a_RATE_6KHz66 0xA0/*加速度 量程选项*/#define IMU_LSM6DS_a_Full_2g 0x00#define IMU_LSM6DS_a_Full_4g 0x08#define IMU_LSM6DS_a_Full_8g 0x0C#define IMU_LSM6DS_a_Full_16g 0x04/*角速度 量程选项*/#define IMU_LSM6DS_w_Full_125dps 0x02#define IMU_LSM6DS_w_Full_245dps 0x00#define IMU_LSM6DS_w_Full_500dps 0x04#define IMU_LSM6DS_w_Full_1000dps 0x08#define IMU_LSM6DS_w_Full_2000dps 0x0C/* 加速度带宽 选项*/#define IMU_LSM6DS_a_BW_1KHz5 0x00#define IMU_LSM6DS_a_BW_400Hz 0x01/* 加速度计低通滤波 选项 */#define IMU_LSM6DS_a_LOW_PASS_ODR_9 0xC8#define IMU_LSM6DS_a_LOW_PASS_ODR_50 0x88#define IMU_LSM6DS_a_LOW_PASS_ODR_100 0xA8#define IMU_LSM6DS_a_LOW_PASS_ODR_400 0xE8/*角速度计 高通滤波器 选项 */#define IMU_LSM6DS_w_HP_DISABLE 0x00#define IMU_LSM6DS_w_HP_ENABLE 0x40/*角速度计 高通滤波器截止频率 选项 */#define IMU_LSM6DS_w_HPM_16MHz 0x00#define IMU_LSM6DS_w_HPM_65MHz 0x10#define IMU_LSM6DS_w_HPM_260MHz 0x20#define IMU_LSM6DS_w_HPM_1Hz04 0x30/*角速度计 低通滤波带宽 选项 */#define IMU_LSM6DS_w_CTRL6_C_FTYPE_1 0x00#define IMU_LSM6DS_w_CTRL6_C_FTYPE_2 0x01#define IMU_LSM6DS_w_CTRL6_C_FTYPE_3 0x02#define IMU_LSM6DS_w_CTRL6_C_FTYPE_4 0x03/*FIFO 加速度 速率 选项*/#define IMU_LSM6DS_FIFO_a_12Hz5 0x01#define IMU_LSM6DS_FIFO_a_26Hz 0x02#define IMU_LSM6DS_FIFO_a_52Hz 0x03#define IMU_LSM6DS_FIFO_a_104Hz 0x04#define IMU_LSM6DS_FIFO_a_208Hz 0x05#define IMU_LSM6DS_FIFO_a_417Hz 0x06#define IMU_LSM6DS_FIFO_a_833Hz 0x07#define IMU_LSM6DS_FIFO_a_1667Hz 0x08#define IMU_LSM6DS_FIFO_a_3333Hz 0x09#define IMU_LSM6DS_FIFO_a_6667Hz 0x0A#define IMU_LSM6DS_FIFO_a_6Hz5 0x0B/*FIFO 角速度 速率 选项*/#define IMU_LSM6DS_FIFO_w_12Hz5 0x10#define IMU_LSM6DS_FIFO_w_26Hz 0x20#define IMU_LSM6DS_FIFO_w_52Hz 0x30#define IMU_LSM6DS_FIFO_w_104Hz 0x40#define IMU_LSM6DS_FIFO_w_208Hz 0x50#define IMU_LSM6DS_FIFO_w_417Hz 0x60#define IMU_LSM6DS_FIFO_w_833Hz 0x70#define IMU_LSM6DS_FIFO_w_1667Hz 0x80#define IMU_LSM6DS_FIFO_w_3333Hz 0x90#define IMU_LSM6DS_FIFO_w_6667Hz 0xA0#define IMU_LSM6DS_FIFO_w_6Hz5 0xB0#endif
IMU.h
#ifndef _IMU_H_#define _IMU_H_#include \"HZ_I2C.h\"#include \"Print.h\"#include \"main.h\"#include \"IMU_LSM6DS.h\"#include \"IMU_LIS2MD.h\"/*LSM6DS: 1.软件IIC 2个GPIO 开漏输出 最高速度 */#define IMU_IIC_Soft// #define IMU_LSM6DS_IIC_Hard#ifdef IMU_IIC_Soft#define IMU_SDA_GPIOx GPIOA#define IMU_SDA_Pin GPIO_PIN_4#define IMU_SCL_GPIOx GPIOA#define IMU_SCL_Pin GPIO_PIN_5#define IMU_IIC_Delay 0x1#endif // IMU_IIC_Soft#define IMU_LSM6DS_Addr 0xD6#define IMU_LIS2MD_Addr 0x3Cvoid IMU_I2C_Init(void);uint8_t IMU_LSM6DS_I2C_Read_Reg8(uint8_t reg);uint8_t IMU_LSM6DS_I2C_Write_Reg8(uint8_t reg, uint8_t data);uint8_t IMU_LSM6DS_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf);uint8_t IMU_LIS2MD_I2C_Read_Reg8(uint8_t reg);uint8_t IMU_LIS2MD_I2C_Write_Reg8(uint8_t reg, uint8_t data);uint8_t IMU_LIS2MD_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf);int IMU_LSM6DS_Init(void);void IMU_Delay(uint32_t time);int8_t IMU_LSM6DS_GetState_a(void);int8_t IMU_LSM6DS_GetState_w(void);int8_t IMU_LSM6DS_GetState_t(void);void IMU_LSM6DS_Print_data(void);int8_t IMU_LSM6DS_Get_a(float *ax, float *ay, float *az);int8_t IMU_LSM6DS_Get_w(float *wx, float *wy, float *wz);float IMU_LSM6DS_Get_t(void);int IMU_LIS2MD_Init(void);uint8_t IMU_LIS2MD_Get_State(void);void IMU_LIS2MD_Print_data(void);int IMU_LIS2MD_Get_Magnetic(float *mx, float *my, float *mz);float IMU_LIS2MD_Get_T(void);uint16_t IMU_LSM6DS_Get_FIFO_num(void);float IMU_LSM6DS_Get_FIFO_Data(void);uint16_t IMU_LSM6DS_Get_FIFO_Data_TGA(void);#endif
IMU_LIS2MD.c
#include \"IMU.h\"// IMU_LIS2MD_/** * @brief 设置BDU(块数据更新) * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 14:15:28 */int IMU_LIS2MD_Set_BDU(uint8_t flag){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C); // 读取控制寄存器C // 写入寄存器 if (flag) temp |= 0x10; // bit 4 写1 else temp &= 0xEF; // bit 4 清零 IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_C, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C); if (temp & 0x10) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}/** * @brief LIS2MD复位 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 13:58:46 */int IMU_LIS2MD_Restart(void){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); temp |= 0x20; if (IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp)) return -1; IMU_Delay(20); return 0;}/** * @brief 读取ID * @return ID * @author HZ12138 * @date 2025-07-18 13:35:33 */uint8_t IMU_LIS2MD_Read_ID(void){ return IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_ID);}/** * @brief 设置输出速率 * @param opt 选项( IMU_LIS2MD_ODR_10Hz /...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 15:35:04 */int IMU_LIS2MD_Set_ODR(uint8_t opt){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); temp |= opt; IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp); temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); if ((temp & 0x0C) != opt) return -1; return 0;}/** * @brief 设置偏移消除 * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 16:39:28 */int IMU_LIS2MD_Set_Offset_CANC(uint8_t flag){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B); // 读取控制寄存器B // 写入寄存器 if (flag) temp |= 0x02; // bit 1 写1 else temp &= 0xFD; // bit 1 清零 IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_B, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B); if (temp & 0x02) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}/** * @brief 设置温度补偿 * @param flag 0禁用 1启用 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 16:45:30 */int IMU_LIS2MD_Set_TempComp(uint8_t flag){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A // 写入寄存器 if (flag) temp |= 0x80; // bit 1 写1 else temp &= 0x7F; // bit 1 清零 IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); if (temp & 0x80) { if (!flag) // 读取的是1 期望的是0 return -1; } else { if (flag) // 读取的是0 期望的是1 return -1; } return 0;}/** * @brief 设置模式 * @param opt 选项(IMU_LIS2MD_MODE_Continuous/...) * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 17:10:08 */int IMU_LIS2MD_Set_Mode(uint8_t opt){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A temp &= 0xFC; temp |= opt; IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp); // 读取验证是否成功 temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); if ((temp & 0x03) != opt) return -1; return 0;}/** * @brief 初始化LIS2MD * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 13:32:30 */int IMU_LIS2MD_Init(void){ if (IMU_LIS2MD_Read_ID() != 0x40) // 验证ID return -1; if (IMU_LIS2MD_Restart() != 0) // 复位 return -2; if (IMU_LIS2MD_Set_BDU(1) != 0) // 设置块数据更新 return -3; if (IMU_LIS2MD_Set_ODR(IMU_LIS2MD_ODR_50Hz) != 0) // 设置数据更新速率 return -4; if (IMU_LIS2MD_Set_Offset_CANC(1) != 0) // 设置偏移消除 return -5; if (IMU_LIS2MD_Set_TempComp(1) != 0) // 设置温度补偿 return -6; HAL_Delay(10); if (IMU_LIS2MD_Set_Mode(IMU_LIS2MD_MODE_Continuous) != 0) // 启动连续模式 return -7; return 0;}/** * @brief 获取数据状态 * @return 0 没有准备好 1 准备完成 * @author HZ12138 * @date 2025-07-18 21:01:46 */uint8_t IMU_LIS2MD_Get_State(void){ uint8_t temp; temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_STATUS); // 读取状态寄存器 if (temp & 0x08) return 1; return 0;}/** * @brief 获取磁场数据 单位 mG(毫高斯) * @param mx x方向磁场 * @param my y方向磁场 * @param mz z方向磁场 * @return 0成功 <0失败 * @author HZ12138 * @date 2025-07-18 21:01:44 */int IMU_LIS2MD_Get_Magnetic(float *mx, float *my, float *mz){ uint8_t buf[6]; int16_t temp_mx, temp_my, temp_mz; if (IMU_LIS2MD_I2C_Read_Len_Reg8(0x68, 6, buf)) return -1; temp_mx = (buf[1] << 8) | buf[0]; temp_my = (buf[3] << 8) | buf[2]; temp_mz = (buf[5] << 8) | buf[4]; *mx = (float)temp_mx * 1.5f; *my = (float)temp_my * 1.5f; *mz = (float)temp_mz * 1.5f; return 0;}/** * @brief 获取温度 * @return 温度 (℃) * @author HZ12138 * @date 2025-07-18 21:20:59 */float IMU_LIS2MD_Get_T(void){ uint8_t buf[2]; int16_t temp; IMU_LIS2MD_I2C_Read_Len_Reg8(0x6E, 2, buf); temp = (buf[1] << 8 | buf[0]); return (((float)temp / 8.0f) + 25.0f);}/** * @brief 打印数据 * @author HZ12138 * @date 2025-07-18 21:21:31 */void IMU_LIS2MD_Print_data(void){ float mx, my, mz; float t; if (!IMU_LIS2MD_Get_State()) return; IMU_LIS2MD_Get_Magnetic(&mx, &my, &mz); t = IMU_LIS2MD_Get_T(); printf(\"%f,%f,%f,%f\\n\", mx, my, mz, t);}
IMU_LIS2MD.h
#ifndef _IMU_LIS2MD_H_#define _IMU_LIS2MD_H_#define IMU_LIS2MD_REG_ID 0x4F // ID寄存器#define IMU_LIS2MD_REG_CFG_A 0x60 // 控制寄存器A#define IMU_LIS2MD_REG_CFG_B 0x61 // 控制寄存器B#define IMU_LIS2MD_REG_CFG_C 0x62 // 控制寄存器C#define IMU_LIS2MD_REG_STATUS 0x67 // 状态寄存器/* 数据输出 选项 */#define IMU_LIS2MD_ODR_10Hz 0x00#define IMU_LIS2MD_ODR_20Hz 0x04#define IMU_LIS2MD_ODR_50Hz 0x08#define IMU_LIS2MD_ODR_100Hz 0x0C/* 模式设置 选项 */#define IMU_LIS2MD_MODE_Idle 0x11#define IMU_LIS2MD_MODE_Single 0x01#define IMU_LIS2MD_MODE_Continuous 0x00#endif
IMU_I2C.c
#include \"IMU.h\"#ifdef IMU_IIC_SoftHZ_I2C_typedef IMU_I2C_h;#endif // IMU_IIC_Soft/** * @brief 初始化I2C * @author HZ12138 * @date 2025-07-15 17:50:23 */void IMU_I2C_Init(void){#ifdef IMU_IIC_Soft // 使用软件IIC 绑定地址 // 绑定SDA和SCL到IIC句柄 I2C_Init_Channel(&IMU_I2C_h, IMU_SDA_GPIOx, IMU_SDA_Pin, IMU_SCL_GPIOx, IMU_SCL_Pin, IMU_IIC_Delay); // addr D6#endif // IMU_IIC_Soft}/** * @brief 读8bits寄存器 * @param reg 寄存器地址 * @return 读取的数据 * @author HZ12138 * @date 2025-07-15 17:49:51 */uint8_t IMU_LSM6DS_I2C_Read_Reg8(uint8_t reg){#ifdef IMU_IIC_Soft return I2C_Read_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg);#endif // IMU_IIC_Soft}/** * @brief 写8bits寄存器 * @param reg:寄存器地址 8bit * @param data:数据 * @return 状态 0成功 其他失败 * @author HZ12138 * @date 2025-07-15 19:22:28 */uint8_t IMU_LSM6DS_I2C_Write_Reg8(uint8_t reg, uint8_t data){#ifdef IMU_IIC_Soft return I2C_Write_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, data);#endif // IMU_IIC_Soft}/** * @brief I2C连续读寄存器 * @param reg 寄存器地址 * @param len 长度 * @param buf 缓冲区地址 * @author HZ12138 * @date 2025-07-16 17:19:58 */uint8_t IMU_LSM6DS_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf){#ifdef IMU_IIC_Soft return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, len, buf);#endif // IMU_IIC_Soft}/** * @brief 读8bits寄存器 * @param reg 寄存器地址 * @return 读取的数据 * @author HZ12138 * @date 2025-07-15 17:49:51 */uint8_t IMU_LIS2MD_I2C_Read_Reg8(uint8_t reg){#ifdef IMU_IIC_Soft return I2C_Read_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg);#endif // IMU_IIC_Soft}/** * @brief 写8bits寄存器 * @param reg:寄存器地址 8bit * @param data:数据 * @return 状态 0成功 其他失败 * @author HZ12138 * @date 2025-07-15 19:22:28 */uint8_t IMU_LIS2MD_I2C_Write_Reg8(uint8_t reg, uint8_t data){#ifdef IMU_IIC_Soft return I2C_Write_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, data);#endif // IMU_IIC_Soft}/** * @brief I2C连续读寄存器 * @param reg 寄存器地址 * @param len 长度 * @param buf 缓冲区地址 * @author HZ12138 * @date 2025-07-16 17:19:58 */uint8_t IMU_LIS2MD_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf){#ifdef IMU_IIC_Soft return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, len, buf);#endif // IMU_IIC_Soft}