LIS2DW12,LIS2DH,LIS3DH驱动基本一样。
一、首先获取官方驱动文件,不要自己写寄存器,浪费时间还容易出错。


官方提供了各个功能的例程,然后移植你自己需要的。
二、LIS2DW12的常用功能,
1.轮询模式
2.fifo+中断模式
3.唤醒模式
三、具体代码配置
1.轮询模式
//轮询模式
uint8_t lis2dw12_config_polling(void)
{
/* Enable Block Data Update. */
lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);//量程
//platform_delay(1);
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT);//低通滤波
//platform_delay(1);
lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_4);//带宽
//platform_delay(1);LIS2DW12_HIGH_PERFORMANCE 、 LIS2DW12_CONT_LOW_PWR_LOW_NOISE_4
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_HIGH_PERFORMANCE);//高性能
//platform_delay(1);
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_25Hz);//频率
dev_ctx.mdelay(5);
return 1;
}
//轮询获取数据XYZ
uint8_t lis2dw12_polling_get_data(float *data)
{
uint8_t ret = 0;
uint8_t reg;
//printf("2\r\n");
lis2dw12_flag_data_ready_get(&dev_ctx, ®);
if (reg)
{
//printf("2\r\n");
/* Read accelerometer data */
memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
lis2dw12_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
acceleration_mg[0] =
lis2dw12_from_fs2_to_mg(data_raw_acceleration[0]);
acceleration_mg[1] =
lis2dw12_from_fs2_to_mg(data_raw_acceleration[1]);
acceleration_mg[2] =
lis2dw12_from_fs2_to_mg(data_raw_acceleration[2]);
memcpy(data, acceleration_mg, 12);
//printf(" x :%.2f, y :%.2f, z :%.2f\r\n",acceleration_mg[0],acceleration_mg[1],acceleration_mg[2]);
//printf("x %.2f,y %.2f,z %.2f\r\n" ,data[0],data[1],data[2]);
ret = 1;
}
return ret;
}
2.fifo模式,FIFO分为好几种模式,常用的是新数据会覆盖旧数据,还有就是新数据不会覆盖旧数据,要读取完旧数据才会继续采样最新的数据,配置具体看数据手册的5.3

//fifo新数据覆盖旧数据
uint8_t lis2dw12_config_fifo_stream(void)
{
dev_ctx.mdelay(2);
/* Enable Block Data Update */
lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT);
lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_2);
/* Configure FIFO */
lis2dw12_fifo_watermark_set(&dev_ctx, 30);
lis2dw12_fifo_mode_set(&dev_ctx, LIS2DW12_STREAM_MODE);
/* Configure power mode */
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_HIGH_PERFORMANCE);
// lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_CONT_LOW_PWR_LOW_NOISE_12bit);
/* Set Output Data Rate */
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_12Hz5);
dev_ctx.mdelay(2);
return 1;
}
//fifo 新数据不覆盖旧数据,需要读取才能继续更新 打开INT1使能中断
uint8_t lis2dw12_config_fifo_int1(void)
{
dev_ctx.mdelay(2);
/* Enable Block Data Update */
lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
// platform_delay(1);
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
// platform_delay(1);
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT); // 低通
// platform_delay(1);
lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_2); // 带通
/* Configure power mode */
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_HIGH_PERFORMANCE); // 禁止低噪声高性能模式
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_12Hz5);
lis2dw12_fifo_watermark_set(&dev_ctx, 30); // fifo个数
lis2dw12_fifo_mode_set(&dev_ctx, LIS2DW12_FIFO_MODE); // FIFO新数据不会覆盖旧数据模式,需要读取后才继续更新
// #if LIS2DW12_INT1_ENABLE
lis2dw12_pin_int1_route_get(&dev_ctx, &int_route.ctrl4_int1_pad_ctrl);
int_route.ctrl4_int1_pad_ctrl.int1_fth = PROPERTY_ENABLE; // 阈值溢出中断
lis2dw12_pin_int1_route_set(&dev_ctx, &int_route.ctrl4_int1_pad_ctrl);
// #endif
dev_ctx.mdelay(2);
return 1;
}
//获取FIFO数据
uint8_t lis2dw12_polling_get_fifo(float *data,uint8_t *fifo_len)
{
uint8_t val, i;
lis2dw12_fifo_wtm_flag_get(&dev_ctx, &val);
if (val)
{
lis2dw12_fifo_data_level_get(&dev_ctx, &val);
*fifo_len = val;
//printf("fifo=%d,\r\n",*fifo);
for (i = 0; i < val; i++) {
/* Read acceleration data */
memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
lis2dw12_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
acceleration_mg[0] = lis2dw12_from_fs2_to_mg(
data_raw_acceleration[0]);
acceleration_mg[1] = lis2dw12_from_fs2_to_mg(
data_raw_acceleration[1]);
acceleration_mg[2] = lis2dw12_from_fs2_to_mg(
data_raw_acceleration[2]);
data[i*3+0] = acceleration_mg[0];
data[i*3+1] = acceleration_mg[1];
data[i*3+2] = acceleration_mg[2];
}
//memcpy(acc,fifo_acc,12*val);
}
else
{
return 0;
}
return 1;
}
3.唤醒模式和单机模式也是常用的,需要配合中断使用。
//单击模式
uint8_t lis2dw12_config_tap_single(void)
{
dev_ctx.mdelay(2);
/* Set full scale */
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
/* Configure power mode */
lis2dw12_power_mode_set(&dev_ctx,
LIS2DW12_CONT_LOW_PWR_LOW_NOISE_12bit);
/* Set Output Data Rate */
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_400Hz);
/* Enable Tap detection on X, Y, Z */
lis2dw12_tap_detection_on_z_set(&dev_ctx, PROPERTY_ENABLE);
lis2dw12_tap_detection_on_y_set(&dev_ctx, PROPERTY_ENABLE);
lis2dw12_tap_detection_on_x_set(&dev_ctx, PROPERTY_ENABLE);
/* Set Tap threshold on all axis */
lis2dw12_tap_threshold_x_set(&dev_ctx, 1);//阈值,时候固定安装
lis2dw12_tap_threshold_y_set(&dev_ctx, 1);
lis2dw12_tap_threshold_z_set(&dev_ctx, 1);
/* Configure Single Tap parameter */
lis2dw12_tap_quiet_set(&dev_ctx, 1);
lis2dw12_tap_shock_set(&dev_ctx, 2);
/* Enable Single Tap detection only */
lis2dw12_tap_mode_set(&dev_ctx, LIS2DW12_ONLY_SINGLE);
/* Enable single tap detection interrupt */
//int1中断
lis2dw12_pin_int1_route_get(&dev_ctx, &int_route.ctrl4_int1_pad_ctrl);
int_route.ctrl4_int1_pad_ctrl.int1_single_tap = PROPERTY_ENABLE;//单击中断源
lis2dw12_pin_int1_route_set(&dev_ctx, &int_route.ctrl4_int1_pad_ctrl);
dev_ctx.mdelay(2);
return 1;
}
//唤醒模式
uint8_t lis2dw12_config_wake_up(void)
{
dev_ctx.mdelay(2);
/* Set full scale */
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
/* Configure power mode */
lis2dw12_power_mode_set(&dev_ctx,
LIS2DW12_CONT_LOW_PWR_LOW_NOISE_12bit);
/* Set Output Data Rate */
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_100Hz);
/* Apply high-pass digital filter on Wake-Up function */
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT);
/* Apply high-pass digital filter on Wake-Up function
* Duration time is set to zero so Wake-Up interrupt signal
* is generated for each X,Y,Z filtered data exceeding the
* configured threshold
*/
lis2dw12_wkup_dur_set(&dev_ctx, 0);
/* Set wake-up threshold
* Set Wake-Up threshold: 1 LSb corresponds to FS_XL/2^6
*/
lis2dw12_wkup_threshold_set(&dev_ctx, 1); // 灵敏度
lis2dw12_pin_int1_route_get(&dev_ctx, &int_route.ctrl4_int1_pad_ctrl);
int_route.ctrl4_int1_pad_ctrl.int1_wu = PROPERTY_ENABLE; // 唤醒源
lis2dw12_pin_int1_route_set(&dev_ctx, &int_route.ctrl4_int1_pad_ctrl);
dev_ctx.mdelay(2);
return 1;
}
驱动代码基本就是这样子,更多功能要看数据手册,顺便说一下IIC驱动和功耗问题。
IIC驱动,我使用的是硬件IIC,驱动文件的lis2dw12.c里面已经封装了读写函数,只需要把自己IIC的驱动替换就上去好了。
#ifdef LIS2DW12DRIVE_MODE_I2C_ENABLE
#if CONFIG_I2C_HARD
#include "./py_iic/py_i2c_hard.h"
#else
#include "./py_iic/py_iic.h"
#endif
#define I2Cx_SLAVE_ADDRESS (0x19 << 1)
#define I2Cx_CLOCK 10000
#endif
//写数据
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len)
{
if (len > 1){
reg = reg | 0x80;
}
#if CONFIG_I2C_HARD
return py_i2c_hard_write_buff(I2Cx_SLAVE_ADDRESS,reg,bufp,len,1);
#endif
#if CONFIG_I2C_SOFT
return i2c_sotf_write_buff(I2Cx_SLAVE_ADDRESS,reg,bufp,len,1);
#endif
}
//读数据
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
if (len > 1){
reg = reg | 0x80;
}
#if CONFIG_I2C_HARD
return py_i2c_hard_read_buff(I2Cx_SLAVE_ADDRESS,reg,bufp,len,1);
#endif
#if CONFIG_I2C_SOFT
return i2c_sotf_read_buff(I2Cx_SLAVE_ADDRESS,reg,bufp,len,1);
#endif
}
uint8_t lis2dw12_config_mode(Lis2dw12ConfigMode mode)
{
static uint8_t start=0;
// uint8_t ret=0;
if(start == 0)
{
dev_ctx.handle = NULL;
dev_ctx.mdelay = platform_delay;
dev_ctx.write_reg = platform_write;
dev_ctx.read_reg = platform_read;
#if LIS2DW12_INT1_ENABLE
lis2dw12_platform_int1_init();
#endif
start = 1;
}
dev_ctx.mdelay(50);
lis2dw12_device_id_get(&dev_ctx, &whoamI);
if (whoamI != LIS2DW12_ID) {
printf("lis2dw12-error id = %x\r\n",whoamI);
return 0;
}
//恢复默认设置
lis2dw12_reset_set(&dev_ctx, PROPERTY_ENABLE);
dev_ctx.mdelay(50);
// do {
// lis2dw12_reset_get(&dev_ctx, &rst);
// } while (rst);
switch (mode)
{
case LIS2DW12_LOW_POWER_STANDBY:
lis2dw12_config_low_power_standby();
break;
case LIS2DW12_POLLING_MODE:
lis2dw12_config_polling();
break;
case LIS2DW12_FIFO_STREAM_MODE:
lis2dw12_config_fifo_stream();
break;
case LIS2DW12_FIFO_INT1_MODE:
lis2dw12_config_fifo_int1();
break;
case LIS2DW12_TAP_SINGLE_MODE:
lis2dw12_config_tap_single();
break;
case LIS2DW12_WAKEUP_MODE:
lis2dw12_config_wake_up();
break;
default:
return 0;
break;
}
return 1;
}
类似封装一下,更方便调用。
功耗方面:

影响加速度传感器功耗最主要的就是性能模式和频率。
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_CONT_LOW_PWR_12bit);//低功耗12位
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_1Hz6_LP_ONLY);//频率
设置成LOW-POWER MODE 1,1.6赫兹,最低功耗连1uA不到,
/* Configure power mode */
lis2dw12_power_mode_set(&dev_ctx,
LIS2DW12_CONT_LOW_PWR_LOW_NOISE_12bit);
/* Set Output Data Rate */
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_100Hz);
唤醒模式,LIS2DW12_CONT_LOW_PWR_LOW_NOISE_12bit,LIS2DW12_XL_ODR_100Hz才7uA,可以在休眠状态下判断是否震动。
数据可视化,看下水平时放置时数据波动。
qt自己写个上位机,使用qcustomplot模块
加速度矢量值

看下噪声干扰,使用方差的方式

电路图:
