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_Soft
HZ_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_Softreturn 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_Softreturn 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_Softreturn 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 写1temp |= 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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清零后写入opttemp &= 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 清零后写入opttemp &= 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清零后写入opttemp &= 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 期望的是0return -2;}else{if (en) // 读取的是0 期望的是1return -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 置1temp |= 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(); // 初始化IICif (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测IDreturn -1;IMU_LSM6DS_ReStart(); // 软复位if (IMU_LSM6DS_SetBDU(1)) // 设置BDUreturn -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()) // 设置Int1return -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_Soft
HZ_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_Softreturn 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_Softreturn 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_Softreturn 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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); // 读取控制寄存器Atemp &= 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) // 验证IDreturn -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 写1temp |= 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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清零后写入opttemp &= 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 清零后写入opttemp &= 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清零后写入opttemp &= 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 期望的是0return -2;}else{if (en) // 读取的是0 期望的是1return -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 置1temp |= 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(); // 初始化IICif (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测IDreturn -1;IMU_LSM6DS_ReStart(); // 软复位if (IMU_LSM6DS_SetBDU(1)) // 设置BDUreturn -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()) // 设置Int1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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); // 读取控制寄存器Atemp &= 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) // 验证IDreturn -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_Soft
HZ_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_Softreturn 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_Softreturn 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_Softreturn 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_Softreturn 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_Softreturn 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_Softreturn I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, len, buf);
#endif // IMU_IIC_Soft
}