LSM6DS3TH-C 6軸傳感器驅動


LSM6DS3TH-C 6軸傳感器驅動

說明

  • 測試平台:STM32F4
  • 使用說明:
    • 在platform_ReadByte、與platform_WriteByte中實現對應平台的I2C讀寫操作接口
    • 默認應用接口為弱定義,定義此USER_APP_INTERFACE宏定義可以開啟示例的應用接口,用戶可自定義自己的接口函數,打印信息可自行關閉,默認的接口函數不包含單位轉換,只實現了原始數據存儲
    • 存儲數據使用數據類型sLSM6DS3_Data
    • 默認定義了對象sLSM6DS3_Dev g_lsm6ds3,可包含lsm6ds3.h頭文件,即可使用此對象去訪問用戶接口函數

驅動源碼

#ifndef __LSM6DS3_H__
#define __LSM6DS3_H__

#include "main.h"

#define LSM6DS3_WHO_AM_I                0X0F // 能讀出ID,根據芯片不同而不同,可能是0x69,也或許是0x6a
#define LSM6DS3_CTRL1_XL                0X10 // 線性加速度傳感器控制寄存器1 (r/w)。
/*  bit7						~						  bit0
	ODR_XL3 ODR_XL2 ODR_XL1 ODR_XL0 FS_XL1 FS_XL0 BW_XL1 BW_XL0
	其中:ODR_XL3 ODR_XL2 ODR_XL1 ODR_XL0 輸出數據速率和電源模式選擇
	FS_XL1 FS_XL0:ACC滿量程選擇
	BW_XL1 BW_XL0:抗混疊濾波器帶寬選擇。
*/
#define LSM6DS3_CTRL2_G                 0X11
/*  bit7						~			   bit0
	ODR_G3  ODR_G2 ODR_G1 ODR_G0 FS_G1  FS_G0 FS_125
	其中:ODR_G3  ODR_G2 ODR_G1 ODR_G0:陀螺儀輸出速率選擇
	FS_G1  FS_G0:陀螺儀滿量程選擇
	FS_125:陀螺儀滿量程為125dps;	
*/
#define LSM6DS3_CTRL3_C                 0X12
/*  bit7						~			   bit0
	BooT BDU H_LACTIVE PP_OD SIM IF_INC BLE SW_RESET
	BooT:重啟內存里的內容
	BDU:更新塊數據
	H_LACTIVE:中斷活躍水平
	PP_OD:INT1和INT2襯墊上的推拉/開式排水選擇。
	SIM:SPI Serial interface mode select
	IF_INC:寄存器地址在進行串行多字節訪問時自動增加
	BLE:大/小端數據選擇
	SW_RESET:軟件復位
*/
#define LSM6DS3_CTRL4_C                 0X13
/*  bit7						~			   bit0
	XL_BW_SCAL_ODR:加速度計帶寬的選擇;
	SLEEP_G:陀螺儀睡眠模式使能;
	INT2_on_INT1:所有中斷信號在INT1上可用
	FIFO_TEMP_EN:使能穩如數據作為4th FIFO數據設置
	DRDY_MASK:數據讀掩碼使能;
	I2C_disable:disable i2c接口
	0
	STOP_ON_FTH:啟用FIFO閾值級別使用;
*/
#define LSM6DS3_CTRL5_C                 0X14
/*
	ROUNDING2 ROUNDING1 ROUNDING0 0 ST1_G  ST0_G ST1_XL ST0_XL
	ROUNDING2 ROUNDING1 ROUNDING0:從輸出寄存器中讀取循環突發模式(舍入)。
	ST1_G  ST0_G:角速率傳感器自檢使能。
	ST1_XL ST0_XL:線性加速度傳感器自檢使能。
*/

#define LSM6DS3_CTRL6_C                 0X15
/*
	角速率傳感器控制寄存器
	TRIG_EN LVLen LVL2_EN XL_HM_MODE 0 0 0 0
	TRIG_EN:陀螺儀數據邊緣敏感觸發啟用。
	LVLen:陀螺儀數據電平敏感觸發啟用。
	LVL2_EN:陀螺儀電平敏感鎖存使能。
	XL_HM_MODE:加速計高性能工作模式禁用.
*/
#define LSM6DS3_CTRL7_G                 0X16
/*
	角速率傳感器控制寄存器7
	G_HM_MODE HP_G_EN HPCF_G1 HPCF_G0 HP_G_RST ROUNDING_STATUE 0 0
	G_HM_MODE:陀螺儀的高性能工作模式禁用
	HP_G_EN:陀螺數字高通濾波器使能。只有當陀螺儀處於HP模式時,才啟用過濾器。
	HPCF_G1 HPCF_G0:陀螺儀高通濾波器截止頻率選擇。
	HP_G_RST:陀螺數字HP濾波器復位
	ROUNDING_STATUE:源寄存器四舍五入功能使能在1E,53,1B	
*/
#define LSM6DS3_CTRL8_XL                0X17
/*
	線性加速度傳感器控制寄存器8 (r/w)。
	LPF2_XL_EN	HPCF_XL1 HPCF_XL0 0 0 HP_SLOPE_XL_EN 0 LOW_PASS_ON_6D
	LPF2_XL_EN: 加速度計低通濾波器LPF2選擇。
	HPCF_XL1 HPCF_XL0:加速度計斜率濾波器和高通濾波器配置和截止設置。
		見表68。它還用於選擇LPF2濾波器的截止頻率,如表69所示。通過將CTRL8XL (17h)的LOW PASS ON 6D位設置為1,這種低通濾波器也可以用於6D/4D功能。
	HP_SLOPE_XL_EN:加速度計斜率濾波器/高通濾波器選擇。
	LOW_PASS_ON_6D:低通濾波器對6D功能的選擇。
*/
#define LSM6DS3_CTRL9_XL                0X18
/*
	0 0 Zen_XL Yen_XL Xen_XL SOFT_EN 0 0
	Zen_XL:加速計z軸輸出啟用。
	Yen_XL:加速計y軸輸出啟用。
	Xen_XL:加速計x軸輸出啟用.
	SOFT_EN:啟用磁強計軟鐵校正算法
*/
#define LSM6DS3_CTRL10_C                0X19
/*
	0 0 Zen_G Yen_G Xen_G FUNC_EN FEDO_RST_STEP SIGN_MOTION_EN
	Zen_G:陀螺偏航軸(Z)輸出使能。
	Yen_G:陀螺滾軸(Y)輸出使能。
	Xen_G:陀螺螺距軸(X)輸出使能。
	FUNC_EN:啟用嵌入式功能(計步器、傾斜、顯著運動、傳感器輪轂和熨燙)和加速度計HP和LPF2濾波器
		(參見圖6)。默認值:0
	FEDO_RST_STEP:重置計步器步長計數器。
	SIGN_MOTION_EN:使能重要運動功能
*/

//i2c master config register
#define LSM6DS3_MASTER_CONFIG           0X1A

//interrupts register
#define LSM6DS3_WAKE_UP_SRC             0X1B
/*
	0 0 FF_IA SLEEP_STATE_IA WU_IA X_WU Y_WU Z_WU
	FF_IA:自由落體時間檢測狀態
	SLEEP_STATE_IA:睡眠時間狀態
	WU_IA:喚醒時間檢測狀態
	X_WU:x軸上的喚醒事件檢測狀態。
	Y_WU: y軸上的喚醒事件檢測狀態。
	Z_WU: z軸上的喚醒事件檢測狀態。
*/
#define LSM6DS3_TAP_SRC                 0X1C
/*
	0 TAP_IA SIGLE_TAP DOUBLE_TAP TAP_SIGN X_TAP Y_TAP Z_TAP
	TAP_IA:輕擊事件檢測狀態
	SIGLE_TAP:單擊事件檢測狀態
	DOUBLE_TAP:雙擊事件檢測狀態
	TAP_SIGN:輕擊事件檢測到的加速標志。
	X_TAP Y_TAP Z_TAP:點擊x/y/z軸上的事件檢測狀態
*/
#define LSM6DS3_D6D_SRC                 0X1D
/*
	縱向、橫向、面朝上和面朝下源寄存器(r)
	0 D6D_IA ZH ZL YH YL XH XL 
	D6D_IA:激活中斷以改變位置縱向,橫向,正面向上,正面向下。
	ZH: Z軸高事件(高於閾值)
	ZL:Z軸低事件(低於閾值)
	...
*/
//status data register
#define LSM6DS3_STATUS_REG              0X1E
/*
	- - - - - TDE GDA XLDA
	TDE:溫度可用的新數據
	GDA:陀螺儀可用的新數據
	XLDA:加速度計可用的新數據
*/
#define LSM6DS3_TAP_CFG			0x58
#define LSM6DS3_TAP_THS_6D		0x59
#define LSM6DS3_WAKE_UP_THS	        0x5B
#define LSM6DS3_WAKE_UP_DUR		0x5C
#define LSM6DS3_MD1_CFG			0x5E

//temperature output data register
#define LSM6DS3_OUT_TEMP_L              0X20
#define LSM6DS3_OUT_TEMP_H              0X21
/*溫度數據輸出寄存器(r)。L寄存器和H寄存器一起表示一個16位的字。*/

//gyroscope output register
#define LSM6DS3_OUTX_L_G                0X22
#define LSM6DS3_OUTX_H_G                0X23
#define LSM6DS3_OUTY_L_G                0X24
#define LSM6DS3_OUTY_H_G                0X25
#define LSM6DS3_OUTZ_L_G                0X26
#define LSM6DS3_OUTZ_H_G                0X27

//acc output register
#define LSM6DS3_OUTX_L_XL               0X28
#define LSM6DS3_OUTX_H_XL               0X29
#define LSM6DS3_OUTY_L_XL               0X2A
#define LSM6DS3_OUTY_H_XL               0X2B
#define LSM6DS3_OUTZ_L_XL               0X2C
#define LSM6DS3_OUTZ_H_XL               0X2D

#define LSM6DS3_INT1_CTRL		0X0D
/*
	Write INT1_CTRL = 01h // Acc Data Ready interrupt on INT1
	Write INT1_CTRL = 02h // Gyro Data Ready interrupt on INT1
*/

#define I2C_Handle			hi2c1
#define LSM6DS3_SlaveAddress		0xd4
#define I2C_Status			HAL_StatusTypeDef
#define LSM6DS3_DeviceID		0x6a

//#define USER_APP_INTERFACE
#undef	USER_APP_INTERFACE

// 操作模式讀/寫
typedef enum 
{
	eRead = 0u,
	eWrite = 1u,
} OPmode_t;

// 查詢狀態標志
typedef enum{
    STATUS_XLDA_ACC_E = 0x01, // acc 數據可讀
    STATUS_GDA_GYRO_E = 0x02, // gyro 數據可讀
    STATUS_TDA_TEMP_E = 0x04, // temp 數據可讀
}LSM6DS3_STATUS_t;

// 數據類型
typedef struct 
{
	int16_t data_raw_acceleration[3];
	int16_t data_raw_angular_rate[3];
	int16_t data_raw_temperature;
	float acceleration_mg[3];
	float angular_rate_mdps[3];
	float temperature_degC;
	uint8_t whoamI;
	uint8_t uReaddata;
	uint8_t orientation;
} sLSM6DS3_Data;

typedef struct 
{
	/* I2C句柄,使用IO模擬I2C則設置句柄為NULL */
	void *handle;
	/* 讀數據 */
	sLSM6DS3_Data m_dataBuf;
	/* 設備從機地址 */
	uint8_t slaveAddress;
	/* 設備ID */
	uint8_t deviceID;

	// 接口函數區域
	void (*Init)(void);
	uint8_t (*ReadByte)(uint8_t reg);
	void (*WriteByte)(uint8_t reg, uint8_t data);
	uint16_t (*ReadMultiple)(uint8_t reg_begin, uint8_t reg_end, uint8_t *data);
	
	// 擴展用戶接口,默認為弱定義,用戶可自行實現
	uint8_t (*ReadOrigin)(void);
	uint8_t (*ReadWhoAmI)(void);
	int16_t *(*ReadAngularRateRaw)(int16_t *pbuf);
	int16_t *(*ReadAccelerationRaw)(int16_t *pbuf);
	int16_t *(*ReadTemperatureRaw)(int16_t *pbuf);
	
} sLSM6DS3_Dev;

// 聲明對象
extern sLSM6DS3_Dev g_lsm6ds3;

#endif
#include "LSM6DS3.h"
#include "i2c.h"
#include "debug.h"
#include <string.h>

/* 私有函數聲明區域 */
static void Lsm6ds3_Init(void);
static void Lsm6ds3_WriteByte(uint8_t reg, uint8_t data);
static uint8_t Lsm6ds3_ReadByte(uint8_t reg);
static uint16_t Lsm6ds3_ReadMultiple(uint8_t reg_addr_begin, uint8_t reg_addr_end, uint8_t *data);

uint8_t Lsm6ds3_ReadOrigin(void);
uint8_t Lsm6ds3_ReadWhoAmI(void);
int16_t *Lsm6ds3_ReadAccelerationRaw(int16_t *pbuf);
int16_t *Lsm6ds3_ReadAngularRateRaw(int16_t *pbuf);
int16_t *Lsm6ds3_ReadTemperatureRaw(int16_t *pbuf);

/* lsm6ds3傳感器對象初始化 */
sLSM6DS3_Dev g_lsm6ds3 =
{
	&hi2c1,
	{0},
	LSM6DS3_SlaveAddress,
	LSM6DS3_DeviceID,
	
	Lsm6ds3_Init,
	Lsm6ds3_ReadByte,
	Lsm6ds3_WriteByte,
	Lsm6ds3_ReadMultiple,
	
	Lsm6ds3_ReadOrigin,
	Lsm6ds3_ReadWhoAmI,
	Lsm6ds3_ReadAngularRateRaw,
	Lsm6ds3_ReadAccelerationRaw,
	Lsm6ds3_ReadTemperatureRaw,
};

/*
 * @brief  Read generic device register (platform dependent)
 *
 * @param[in]  handle    customizable argument. In this examples is used in
 *                       order to select the correct sensor bus handler.
 * @param[in]  reg       register to read
 * @param[in]  bufp      pointer to buffer that store the data read
 * @param[in]  len       number of consecutive register to read
 *
 */
static I2C_Status platform_ReadByte(void *handle, uint8_t slaveAddress, uint8_t reg, uint8_t *bufp, uint16_t len)
{
    return HAL_I2C_Mem_Read(handle, slaveAddress, reg, I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);
}

/*
 * @brief  Write generic device register (platform dependent)
 *
 * @param[in]  handle    customizable argument. In this examples is used in
 *                   order to select the correct sensor bus handler.
 * @param[in]  reg       register to write
 * @param[in]  bufp      pointer to data to write in register reg
 * @param[in]  len       number of consecutive register to write
 *
 */
static I2C_Status platform_WriteByte(void *handle, uint8_t slaveAddress, uint8_t reg, uint8_t *bufp, uint16_t len)
{
	return HAL_I2C_Mem_Write(handle, slaveAddress, reg, I2C_MEMADD_SIZE_8BIT, (uint8_t *)bufp, len, 1000);
}

/**
 * @brief      寫入一個字節
 *
 * @param[in]  reg   寄存器地址
 * @param[in]  data  待寫入的數據
 */
static void Lsm6ds3_WriteByte(uint8_t reg, uint8_t data)
{
	I2C_Status ret = platform_WriteByte(g_lsm6ds3.handle,  g_lsm6ds3.slaveAddress | eWrite, 
		reg, &data, sizeof(data));
	if(ret != HAL_OK)
		p_err("error_code:%d", ret);
}

/**
 * @brief      讀取一個字節
 *
 * @param[in]  reg   寄存器地址
 *
 * @return     返回讀取到的數據
 */
static uint8_t Lsm6ds3_ReadByte(uint8_t reg)
{
	I2C_Status ret = platform_ReadByte(g_lsm6ds3.handle,  g_lsm6ds3.slaveAddress | eRead, 
		reg, &(g_lsm6ds3.m_dataBuf.uReaddata), sizeof(g_lsm6ds3.m_dataBuf.uReaddata));
	if(ret != HAL_OK)
	{
		p_err("error_code:%d", ret);
		g_lsm6ds3.m_dataBuf.uReaddata= 0xff;
	}
	p_info("Lsm6ds3_ReadByte ret=%d, reg=0x%x, data=0x%x", ret, reg, g_lsm6ds3.m_dataBuf.uReaddata);
	return g_lsm6ds3.m_dataBuf.uReaddata;
}

/**
 * @brief      連續地址讀取傳感器參數/數據
 *
 * @param[in]  reg_addr_begin  The register address begin
 * @param[in]  reg_addr_end    The register address end
 * @param[out] data            The data
 *
 * @return     返回讀取的字節數
 */
static uint16_t Lsm6ds3_ReadMultiple(uint8_t reg_addr_begin, uint8_t reg_addr_end, uint8_t *data)
{
	uint16_t nCount = 0;
	if(reg_addr_begin > reg_addr_end)
	{
		p_err("register address invalid!");
		return 0;
	}
	
	while(nCount < (reg_addr_end - reg_addr_begin + 1)) 
	{
		data[nCount] = Lsm6ds3_ReadByte(reg_addr_begin + nCount);
		nCount++;
	}
	
	return nCount;
}

/**
 * @brief      初始化陀螺儀和加速度傳感器
 */
static void Lsm6ds3_Init(void)
{
	uint8_t whoAmI = Lsm6ds3_ReadByte(LSM6DS3_WHO_AM_I);
	
	p_info("Lsm6ds3_Init[G-SensorId] -> 0x%x", whoAmI);
	if(whoAmI != LSM6DS3_DeviceID)
	{
		p_err("read who am i failed!");
		return;
	}
	// 加速度計52HZ(傾斜角檢測功能工作在26HZ,因此加速度計ODR必須設置為>=26hz),2g量程。
	Lsm6ds3_WriteByte(LSM6DS3_CTRL1_XL, 0x20);
	// 使能加速度計x,y,z軸
	Lsm6ds3_WriteByte(LSM6DS3_CTRL9_XL, 0x38);
	// enable accelerometer int1
	Lsm6ds3_WriteByte(LSM6DS3_INT1_CTRL, 0x01); 
	
	// 陀螺儀208hz  2000dps
	Lsm6ds3_WriteByte(LSM6DS3_CTRL2_G, 0x5C);
	// 使能陀螺儀x,y,z軸
	Lsm6ds3_WriteByte(LSM6DS3_CTRL10_C, 0x38);

	// WAKE_UP INTERRUPT Configuration
	Lsm6ds3_WriteByte(LSM6DS3_TAP_CFG, 0x90);
	Lsm6ds3_WriteByte(LSM6DS3_WAKE_UP_DUR, 0x00);
	Lsm6ds3_WriteByte(LSM6DS3_WAKE_UP_THS, 0x02);
	Lsm6ds3_WriteByte(LSM6DS3_MD1_CFG, 0x20);
	
	// 6D Orientation Configuration
	Lsm6ds3_WriteByte(LSM6DS3_TAP_THS_6D, 0x40);
	Lsm6ds3_WriteByte(LSM6DS3_CTRL8_XL, 0x01);

	p_info("Lsm6ds3 init successfule!");
}

/****************************************** 應用接口 *********************************************/
#ifdef USER_APP_INTERFACE
/**
 * @brief      獲取傳感器坐標零點
 *
 * @return     見#define LSM6DS3_D6D_SRC
 */
uint8_t Lsm6ds3_ReadOrigin(void)
{
	g_lsm6ds3.m_dataBuf.orientation = Lsm6ds3_ReadByte(LSM6DS3_D6D_SRC); 
	return g_lsm6ds3.m_dataBuf.orientation;
}

/**
 * @brief      獲取芯片ID
 *
 * @return     返回芯片ID
 */
uint8_t Lsm6ds3_ReadWhoAmI(void)
{
	g_lsm6ds3.m_dataBuf.whoamI = Lsm6ds3_ReadByte(LSM6DS3_WHO_AM_I); 
	return g_lsm6ds3.m_dataBuf.whoamI;
}

/**
 * @brief      讀取角速度寄存器原始值
 *
 * @param[out] pbuf  The pbuf
 *
 * @return     返回角速度寄存器原始值(帶符號數值)
 */
int16_t *Lsm6ds3_ReadAngularRateRaw(int16_t *pbuf)
{
	// 讀取寄存器值使用無符號類型,讀取后取值再轉為有符號
	uint8_t buf[6] = {0};

	if((g_lsm6ds3.ReadByte(LSM6DS3_STATUS_REG) & STATUS_GDA_GYRO_E) != 0)
	{
		Lsm6ds3_ReadMultiple(LSM6DS3_OUTX_L_G, LSM6DS3_OUTZ_H_G, buf);
		g_lsm6ds3.m_dataBuf.data_raw_angular_rate[0] = (buf[1] << 8) | buf[0];
		g_lsm6ds3.m_dataBuf.data_raw_angular_rate[1] = (buf[3] << 8) | buf[2];
		g_lsm6ds3.m_dataBuf.data_raw_angular_rate[2] = (buf[5] << 8) | buf[4];
	}
	
	if(NULL != pbuf)
		memcpy(pbuf, buf, sizeof(buf));
	
	return g_lsm6ds3.m_dataBuf.data_raw_angular_rate;
}

/**
 * @brief      讀取加速度寄存器原始值
 *
 * @param[out] pbuf  The pbuf
 *
 * @return     返回加速度寄存器原始值(帶符號數值)
 */
int16_t *Lsm6ds3_ReadAccelerationRaw(int16_t *pbuf)
{
	// 讀取寄存器值使用無符號類型,讀取后取值再轉為有符號
	uint8_t buf[6] = {0};

	if((g_lsm6ds3.ReadByte(LSM6DS3_STATUS_REG) & STATUS_XLDA_ACC_E) != 0)
	{
		Lsm6ds3_ReadMultiple(LSM6DS3_OUTX_L_XL, LSM6DS3_OUTZ_H_XL, buf);
		g_lsm6ds3.m_dataBuf.data_raw_acceleration[0] = (buf[1] << 8) | buf[0];
		g_lsm6ds3.m_dataBuf.data_raw_acceleration[1] = (buf[3] << 8) | buf[2];
		g_lsm6ds3.m_dataBuf.data_raw_acceleration[2] = (buf[5] << 8) | buf[4];
	}
	
	if(NULL != pbuf)
		memcpy(pbuf, buf, sizeof(buf));
	
	return g_lsm6ds3.m_dataBuf.data_raw_acceleration;
}

/**
 * @brief      讀取溫度寄存器原始值
 *
 * @param[out] pbuf  The pbuf
 *
 * @return     返回溫度存器原始值(帶符號數值)
 */
int16_t *Lsm6ds3_ReadTemperatureRaw(int16_t *pbuf)
{
	// 讀取寄存器值使用無符號類型,讀取后取值再轉為有符號
	uint8_t buf[2] = {0};

	if((g_lsm6ds3.ReadByte(LSM6DS3_STATUS_REG) & STATUS_TDA_TEMP_E) != 0)
	{
		Lsm6ds3_ReadMultiple(LSM6DS3_OUT_TEMP_L, LSM6DS3_OUT_TEMP_H, buf);
		g_lsm6ds3.m_dataBuf.data_raw_temperature = (buf[1] << 8) | buf[0];
	}
	
	if(NULL != pbuf)
		memcpy(pbuf, buf, sizeof(buf));
	
	return &(g_lsm6ds3.m_dataBuf.data_raw_temperature);
}
#else
__weak uint8_t Lsm6ds3_ReadOrigin(void)
{
	return 0xff;
}

__weak uint8_t Lsm6ds3_ReadWhoAmI(void)
{
	return 0xff;
}

__weak int16_t *Lsm6ds3_ReadAngularRateRaw(int16_t *pbuf)
{
	return NULL;
}

__weak int16_t *Lsm6ds3_ReadAccelerationRaw(int16_t *pbuf)
{
	return NULL;
}

__weak int16_t *Lsm6ds3_ReadTemperatureRaw(int16_t *pbuf)
{
	return NULL;
}
#endif


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM