一、LSM6DS3TR六轴传感器驱动及数据读取(内附完整代码及注释)
目录
一、LSM6DS3TR简介
二、LSM6DS3TR驱动
1、对芯片进行复位操作
2、读取WHO AM I寄存器返回值,验证通讯是否可靠
3、设置加速度计输出速率和满量程选择
4、设置陀螺仪输出速率和满量程选择
5、设置加速度计BW带宽
6、驱动代码
三、LSM6DS3TR传感器数据读取
四、如果我的文章能帮助到你,请点个赞再走吧(≧∇≦)ノ
一、LSM6DS3TR简介
LSM6DS3TR是ST公司生产的一个六轴传感器,包含内置的三轴加速度计和三轴陀螺仪,其中加速度计能够计算X、Y、Z三个方向的加速度数据,如图1所示:

陀螺仪计算X、Y、Z轴三个轴向的角速度,如图2所示:

二、LSM6DS3TR驱动
前言:
本例程驱动把LSM6DS3TR传感器配置为无中断触发,不使用FIFO先进先出寄存器的缓存功能,传感器中陀螺仪输出的三轴角速度和加速度计输出的三轴加速度准备就绪后直接覆盖旧数据,所以每次从传感器输出寄存器读取数据时,获得的都是最新时刻的加速度和角速度值。如果本例程不符合你的功能预期,请参考LSM6DS3TR数据手册进行寄存器配置更改。
本例程的软件开发IDE为Keil5,使用C/C++混合编程,通过IIC通信协议实现主机和从机的通信。对IIC协议不熟悉的同学,可以参考我之前的博文——IIC通信协议详解,两者是完全适配的,如果使用的是硬件IIC或者SPI协议,需要开发者在通信协议上做的工作就减少很多,可以参考其他文章。
以下是驱动LSM6DS3TR传感器需要进行的操作,按操作先后顺序排列:
1、对芯片进行复位操作
传感器复位需要对LSM6DS3TR的CTRL3_C寄存器进行操作,数据手册表明,CTRL3_C寄存器的地址为0x12,其中第8位BOOT位控制传感器芯片是否重启,第1位SW_RESET位控制传感器芯片复位,实践表明,两个寄存器位都会在置1后自动复位。
/***********************************************************************[函数名称]Reset_LSM6D[函数功能]设备复位函数***********************************************************************/void Reset_LSM6D(void){ uint8_t buf[1] = {0}; //创建1字节通信缓存 IIC_Read(CTRL3_C, buf, 1); //读取寄存器配置 buf[0] |= 0x80; //将BOOT位置1,其他位保持不变 IIC_Send(CTRL3_C, buf, 1); //重启芯片 HAL_Delay(15); //等待重启完成 //将芯片中的寄存器配置恢复到出厂配置 IIC_Read(CTRL3_C, buf, 1); //读取寄存器配置 buf[0] |= 0x01; //将SW_RESET位置1,其他位保持不变 IIC_Send(CTRL3_C, buf, 1); //复位芯片 while ( buf[0] & 0x01 ) //等待芯片复位完成 IIC_Read(CTRL3_C, buf, 1); }
2、读取WHO AM I寄存器返回值,验证通讯是否可靠
WHO AM I是只读寄存器,地址为0x0F,其内部1个字节的数据位在出厂时就已经配置好,不可更改。LSM6DS3TR芯片在收到读取WHO AM I寄存器的指令后,会发送固定的0x6A一个字节数据到主机,该寄存器可用于检验主机和从机的通讯有无异常。由于代码简单,且与配置寄存器无关,所以本部分代码没有以函数形式体现,在完整初始化代码中有包含。
3、设置加速度计输出速率和满量程选择
CTRL1_XL寄存器中的ODR_XL[3:0]四位用来配置加速度计的数据输出速率,输出速率配置为208Hz表示加速度计每秒钟输出208个完整的三轴加速度数据,当传感器的输出速率提高后,主机读取数据的速度也要跟上哦,否则会造成资源浪费。
/***********************************************************************[函数名称]SetAccelerateRate_LSM6D[函数功能]设置加速度数据输出速率***********************************************************************/#define RATE_208Hz0x50void SetAccelerateRate_LSM6D(void){uint8_t buf[1] = {0};IIC_Read(CTRL1_XL, buf, 1);//读取CTRL1_XL寄存器值buf[0] |= RATE_208Hz;//设置加速度计的数据输出速率为218HzIIC_Send(CTRL1_XL, buf, 1);//}
CTRL1_XL寄存器中的FS_XL[1:0]两位用来配置加速度计的最大量程选择,根据你的应用场景,参考下表做出选择:
本例程中选择最大量程±4g,传感器最大量程不同,由原始数据转换为可用数据的转换系数也不同,在数据手册中根据自己的配置选择对应的转换系数:
/**************************************************************************[函数名称]SetAccelerateFullScale_LSM6D[函数功能]设置加速度计的满量程**************************************************************************/#define ACC_FSXL_4G 0x08void SetAccelerateFullScale_LSM6D(void){uint8_t buf[1] = {0};IIC_Read(CTRL1_XL, buf, 1);//读取CTRL1_XL寄存器配置buf[0] |= ACC_FSXL_4G;//设置加速度计的满量程IIC_Send(CTRL1_XL, buf, 1);}
4、设置陀螺仪输出速率和满量程选择
CTRL2_G寄存器的ODR_G[3:0]四位用来控制陀螺仪的输出速率,如果同时使用陀螺仪和加速度计的话,建议两者的输出速率保持一致。加速度计的输出速率我设置的是208Hz,陀螺仪保持一致,也为208Hz,ODR_G[3:0]配置为0101,即0x05。
/*****************************************************************************[函数名称]SetAngleSpeedRate_LSM6D[函数功能]设置陀螺仪数据输出速率*****************************************************************************/void SetAngleSpeedRate_LSM6D(void){uint8_t buf[1] = {0};IIC_Read(CTRL2_G, buf, 1);//读取CTRL2_G寄存器的配置buf[0] |= RATE_208Hz;//设置加速度计的数据采样率为208HzIIC_Send(CTRL2_G, buf, 1);}
CTRL2_G寄存器的FS_G[1:0]两位用来控制陀螺仪的最大量程选择,量程越小,能表示的数值越精确,精度越高,我这里配置的是500dps,表示陀螺仪最大能检测每秒钟500°的旋转,像是体操运动员空中转体一圈半,已经能够满足日常生活中的大部分需求。以下是陀螺仪量程和应用场景的对应表,可以参考:
/*****************************************************************************[函数名称]SetAngleSpeedFullScale_LSM6D[函数功能]设置陀螺仪满量程*****************************************************************************/#define GYR_FSG_500 0x04void SetAngleSpeedFullScale_LSM6D(void){uint8_t buf[1] = {0};IIC_Read(CTRL2_G, buf, 1);buf[0] |= GYR_FSG_500;//设置加速度计的最大量程500dpsIIC_Send(CTRL2_G, buf, 1);}
5、设置加速度计BW带宽
CTRL1_XL寄存器中的LPF1_BW_SEL位和加速度计的滤波带宽选择有关,需要结合CTRL8_XL寄存器中的功能位进行配置,官方给了一个参考表Table73(见下文),在这个表中很清晰的给出了配置加速度计带宽和滤波的选择。
BW0_XL位则和高通滤波有关,如果加速度计输出速率>1.67KHz,就需要配置该位,但是我们设置的输出速率是208Hz,所以这个寄存器位可以不管,保持默认状态就可以。
CTRL8_XL寄存器用来控制加速度计的带宽和滤波选择,可以参考下表Table73来进行配置,比较关键的是INPUT_COMPOSITE位,这个位控制输出数据是Low Noise(低噪声)还是Low Latency(低延时),本例程中将CTRL8_XL寄存器中的INPUT_COMPOSITE位置1,使用低噪声模式,更注重加速度计输出数据的精度。
加速度计滤波路径和带宽的选择原理就不详细介绍了,感兴趣的可以在数据手册里面查找,我们配置的输出速率是208Hz,工作频率不算高频,实际应用中噪声也在可接受的范围内,所以这里只是简单配置了一下加速度计的带宽和滤波器试验了一下,陀螺仪的滤波相关寄存器配置保持默认,不影响正常输出。
/**************************************************************************[函数名称]SetAcceleratemeterBW_LSM6d[函数功能]设置加速度计带宽选择**************************************************************************/#define LSM6DS3TRC_ACC_BW0XL_400HZ0x01//加速度计模拟带宽#define LSM6DS3TRC_ACC_LOW_PASS_ODR_50 0x88//低通滤波器void SetAcceleratemeterBW_LSM6d(void){uint8_t buf[1] = {0};IIC_Read(CTRL1_XL, buf, 1);buf[0] |= LSM6DS3TRC_ACC_BW0XL_400HZ;IIC_Send(CTRL1_XL, buf, 1);IIC_Read(CTRL8_XL, buf, 1);buf[0] |= LSM6DS3TRC_ACC_LOW_PASS_ODR_50;IIC_Send(CTRL8_XL, buf, 1);}
6、驱动代码
将上文中的各个函数补充到这个LSM6DS3TR的初始化函数中,就可以实现六轴传感器的正确驱动。
#define ADDR_Read0xD5//IIC读地址#define ADDR_Write0xD4//IIC写地址#define CTRL1_XL0x10//LSM6DS3TR寄存器地址#define CTRL2_G0x11#define CTRL3_C0x12#define CTRL8_XL0x17#define STATUS_REG0x1E//加速度计的模拟链带宽#define LSM6DS3TRC_ACC_BW0XL_1500HZ0x00#define LSM6DS3TRC_ACC_BW0XL_400HZ0x01//加速度计带宽选择#define LSM6DS3TRC_ACC_LOW_PASS_ODR_50 0x88//低通滤波器#define LSM6DS3TRC_ACC_LOW_PASS_ODR_100 0xA8#define LSM6DS3TRC_ACC_LOW_PASS_ODR_9 0xC8#define LSM6DS3TRC_ACC_LOW_PASS_ODR_400 0xE8/**************************************************************************[函数名称]SelfTest_LSM6D[函数功能]检测IIC总线上挂载的设备是否存在**************************************************************************/uint8_t LSM6D::SelfTest_LSM6D(uint8_t addr){uint8_t recAck = 0xFF;//接收变量IIC_Start();//IIC启动信号IIC_SendByte(addr);//发送地址recAck = IIC_MasterRec_Ack();//主机接收ACK信号IIC_Stop();//IIC停止信号return (recAck == 0);}/**************************************************************************[函数名称]Init_LSM6D[函数功能]初始化函数**************************************************************************/BOOL LSM6D::Init_LSM6D(void){if(SelfTest_LSM6D(ADDR_Read) == false)//验证IIC数据线上有无设备return false;Reset_LSM6D();//软件复位uint8_t WhoAmI = 0;//验证通信是否建立IIC_Read(0x0F, &WhoAmI, 1);if(WhoAmI != 0x6A)//如果IIC通信错误return false;//返回falseSetAccelerateRate_LSM6D();//设置加速度计输出速率208HzSetAccelerateFullScale_LSM6D();//设置加速度计满量程+-4gSetAngleSpeedRate_LSM6D();//设置陀螺仪数据输出速率208HzSetAngleSpeedFullScale_LSM6D();//设置陀螺仪满量程500bpsSetAcceleratemeterBW_LSM6d();//设置加速度计BWreturn true;}
三、LSM6DS3TR传感器数据读取
在完成驱动部分代码设计之后,我们就可以实现六轴传感器的正常运行了,并通过LSM6DS3TR传感器中状态寄存器的GDA(陀螺仪)和XLDA(加速度计)标志位,判断陀螺仪和加速度计数据是否准备就绪,从而进行正确的读取。
union{//加速度一级缓存,原始数据struct {int16_t X;int16_t Y;int16_t Z;}m_Data;uint8_t m_Byte[6];}Acceleration;union{//角速度一级缓存,原始数据struct {int16_t X;int16_t Y;int16_t Z;}m_Data;uint8_t m_Byte[6];}AngleSpeed;union {//读状态寄存器的位域struct{//从上到下,位由低到高uint8_t XLDA : 1;//加速度计有效标志位uint8_t GDA : 1;//陀螺仪有效标志位uint8_t TDA : 1;//温度数据有效标志位,不使用uint8_t : 5;//无关位}m_Bit;//位域结构体uint8_t m_Byte;}status;//状态寄存器读取缓存/*****************************************************************************[函数名称]Read_LSM6D[函数功能]定时运行函数,使用定时器15ms调用一次,但是有误差[备 注] 定义坐标轴方向—— x:正前;y:右; z:上实际坐标轴方向—— y:正前;x:右;-z:上由于安装时芯片翻了个个,所以坐标轴方向有变动,注意区分*****************************************************************************/void Read_LSM6D(void){IIC_Read(STATUS_REG, &status.m_Byte, 1);//读状态寄存器的值到缓存if(status.m_Bit.GDA == true)//如果角速度就绪标志位为1{IIC_Read(0x22, AngleSpeed.m_Byte, 6);//读取6字节的角速度数据//转换为 °/s,注意与芯片安装位置的方向对应data.gyro.x = AngleSpeed.m_Data.Y * 17.5f / 1000.0f;//将原始数据转换为°/sdata.gyro.y = AngleSpeed.m_Data.X * 17.5f / 1000.0f;//根据最大量程选择转换系数17.5data.gyro.z = -AngleSpeed.m_Data.Z * 17.5f / 1000.0f;}if(status.m_Bit.XLDA == true)//如果加速度就绪标志位为1{IIC_Read(0x28, Acceleration.m_Byte, 6); //读取6字节的加速度数据//加速度转换为 g/m2,注意方向data.accel.x = Acceleration.m_Data.Y * 0.122f / 1000.0f; //将原始数据转换为g/m²data.accel.y = Acceleration.m_Data.X * 0.122f / 1000.0f; //根据最大量程选择转换系数0.122data.accel.z = -Acceleration.m_Data.Z * 0.122f / 1000.0f;}}
四、如果我的文章能帮助到你,请点个赞再走吧(≧∇≦)ノ
因为篇幅有限,加速度计和陀螺仪的传感器融合算法将在下一篇博客中介绍,下班后的空余时间少哦,博客的更新速度也是非常缓慢,创作不易,如果我的文章能帮助到你,请点个赞再走吧(≧∇≦)ノ~~~