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