LIS3DH低功耗加速度传感器驱动程序

一、芯片核心特性与低功耗设计

LIS3DH是ST公司推出的超低功耗三轴加速度传感器,核心优势在于微安级功耗(低至2μA),支持多种低功耗模式,适用于电池供电设备(如可穿戴、IoT节点)。

低功耗关键特性

  • 工作模式 :正常模式(11μA@100Hz)、低功耗模式(2μA@1Hz)

  • 数据速率:1Hz~5.3kHz可编程,低速率下功耗线性降低

  • 电源管理:支持软复位、睡眠/唤醒控制

  • 中断驱动:通过单击/双击、自由落体等事件唤醒MCU,减少轮询功耗

二、完整驱动程序(模块化设计)

2.1 头文件 lis3dh.h(寄存器定义+函数声明)

c 复制代码
#ifndef __LIS3DH_H
#define __LIS3DH_H

#include <stdint.h>
#include <stdbool.h>

// ==================== I2C地址 ====================
#define LIS3DH_I2C_ADDR 0x18  // SDO接地(默认)
// #define LIS3DH_I2C_ADDR 0x19  // SDO接VCC

// ==================== 寄存器地址 ====================
#define LIS3DH_REG_WHO_AM_I   0x0F  // 设备ID(固定0x33)
#define LIS3DH_REG_CTRL_REG1  0x20  // 控制寄存器1(ODR、低功耗模式)
#define LIS3DH_REG_CTRL_REG4  0x23  // 控制寄存器4(量程、分辨率)
#define LIS3DH_REG_STATUS_REG 0x27  // 状态寄存器(数据就绪)
#define LIS3DH_REG_OUT_X_L    0x28  // X轴加速度低字节
#define LIS3DH_REG_OUT_X_H    0x29  // X轴加速度高字节
#define LIS3DH_REG_OUT_Y_L    0x2A  // Y轴加速度低字节
#define LIS3DH_REG_OUT_Y_H    0x2B  // Y轴加速度高字节
#define LIS3DH_REG_OUT_Z_L    0x2C  // Z轴加速度低字节
#define LIS3DH_REG_OUT_Z_H    0x2D  // Z轴加速度高字节
#define LIS3DH_REG_CTRL_REG2  0x21  // 高通滤波控制
#define LIS3DH_REG_CTRL_REG3  0x22  // 中断控制
#define LIS3DH_REG_INT1_THS   0x32  // 中断1阈值
#define LIS3DH_REG_INT1_DUR   0x33  // 中断1持续时间

// ==================== 枚举定义 ====================
// 数据输出速率(ODR)
typedef enum {
  LIS3DH_ODR_1HZ    = 0x10,  // 1Hz(低功耗)
  LIS3DH_ODR_10HZ   = 0x20,  // 10Hz
  LIS3DH_ODR_25HZ   = 0x30,  // 25Hz
  LIS3DH_ODR_50HZ   = 0x40,  // 50Hz
  LIS3DH_ODR_100HZ  = 0x50,  // 100Hz(正常模式)
  LIS3DH_ODR_POWERDOWN = 0x00 // 掉电模式(最低功耗)
} lis3dh_odr_t;

// 量程(FS)
typedef enum {
  LIS3DH_FS_2G  = 0x00,  // ±2g(灵敏度1mg/LSB)
  LIS3DH_FS_4G  = 0x10,  // ±4g(灵敏度2mg/LSB)
  LIS3DH_FS_8G  = 0x20,  // ±8g(灵敏度4mg/LSB)
  LIS3DH_FS_16G = 0x30   // ±16g(灵敏度12mg/LSB)
} lis3dh_fs_t;

// 工作模式
typedef enum {
  LIS3DH_MODE_NORMAL    = 0x00,  // 正常模式(12位分辨率)
  LIS3DH_MODE_LOW_POWER = 0x08   // 低功耗模式(8位分辨率)
} lis3dh_mode_t;

// ==================== 数据结构 ====================
typedef struct {
  int16_t x;       // X轴原始加速度(16位)
  int16_t y;       // Y轴原始加速度(16位)
  int16_t z;       // Z轴原始加速度(16位)
  float x_g;       // X轴加速度(g)
  float y_g;       // Y轴加速度(g)
  float z_g;       // Z轴加速度(g)
} lis3dh_data_t;

typedef struct {
  uint8_t i2c_addr;       // I2C地址
  lis3dh_fs_t fs;         // 当前量程
  lis3dh_mode_t mode;     // 当前模式
  float sensitivity;      // 灵敏度(mg/LSB)
  bool initialized;       // 初始化标志
} lis3dh_dev_t;

// ==================== 函数声明 ====================
// 底层I2C接口(用户需根据硬件实现)
extern bool i2c_write(uint8_t addr, uint8_t reg, uint8_t data);
extern bool i2c_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
extern void delay_ms(uint32_t ms);

// 传感器驱动函数
bool lis3dh_init(lis3dh_dev_t *dev, uint8_t i2c_addr);  // 初始化传感器
bool lis3dh_config(lis3dh_dev_t *dev, lis3dh_odr_t odr, lis3dh_fs_t fs, lis3dh_mode_t mode);  // 配置参数
bool lis3dh_read_data(lis3dh_dev_t *dev, lis3dh_data_t *data);  // 读取加速度数据
bool lis3dh_enter_low_power(lis3dh_dev_t *dev);  // 进入低功耗模式(掉电)
bool lis3dh_wakeup(lis3dh_dev_t *dev, lis3dh_odr_t odr);  // 唤醒并设置ODR
bool lis3dh_config_click(lis3dh_dev_t *dev, uint8_t threshold, uint8_t duration);  // 配置单击检测(中断唤醒)

#endif // __LIS3DH_H

2.2 源文件 lis3dh.c(驱动逻辑实现)

c 复制代码
#include "lis3dh.h"
#include <math.h>

// ==================== 私有函数 ====================
// 写寄存器
static bool write_reg(lis3dh_dev_t *dev, uint8_t reg, uint8_t data) {
  return i2c_write(dev->i2c_addr, reg, data);
}

// 读寄存器
static bool read_reg(lis3dh_dev_t *dev, uint8_t reg, uint8_t *data) {
  return i2c_read(dev->i2c_addr, reg, data, 1);
}

// 读多个寄存器
static bool read_regs(lis3dh_dev_t *dev, uint8_t reg, uint8_t *buf, uint8_t len) {
  return i2c_read(dev->i2c_addr, reg, buf, len);
}

// 获取灵敏度(mg/LSB)
static float get_sensitivity(lis3dh_fs_t fs, lis3dh_mode_t mode) {
  if (mode == LIS3DH_MODE_LOW_POWER) {
    switch (fs) {
      case LIS3DH_FS_2G: return 16.0f;   // 8位低功耗模式
      case LIS3DH_FS_4G: return 32.0f;
      case LIS3DH_FS_8G: return 62.0f;
      case LIS3DH_FS_16G: return 186.0f;
      default: return 16.0f;
    }
  } else {
    switch (fs) {
      case LIS3DH_FS_2G: return 1.0f;    // 12位正常模式
      case LIS3DH_FS_4G: return 2.0f;
      case LIS3DH_FS_8G: return 4.0f;
      case LIS3DH_FS_16G: return 12.0f;
      default: return 1.0f;
    }
  }
}

// ==================== 公有函数实现 ====================
// 初始化传感器
bool lis3dh_init(lis3dh_dev_t *dev, uint8_t i2c_addr) {
  if (!dev) return false;
  dev->i2c_addr = i2c_addr;
  dev->initialized = false;

  // 读取WHO_AM_I验证连接(固定0x33)
  uint8_t id;
  if (!read_reg(dev, LIS3DH_REG_WHO_AM_I, &id) || id != 0x33) {
    return false;  // 设备未连接或ID错误
  }

  // 软件复位(CTRL_REG5 bit7=1)
  write_reg(dev, 0x24, 0x80);  // CTRL_REG5
  delay_ms(10);

  dev->initialized = true;
  return true;
}

// 配置传感器参数(ODR/量程/模式)
bool lis3dh_config(lis3dh_dev_t *dev, lis3dh_odr_t odr, lis3dh_fs_t fs, lis3dh_mode_t mode) {
  if (!dev || !dev->initialized) return false;

  // 配置CTRL_REG1(ODR+低功耗模式)
  uint8_t ctrl1 = odr;
  if (mode == LIS3DH_MODE_LOW_POWER) ctrl1 |= 0x08;  // 低功耗位
  if (!write_reg(dev, LIS3DH_REG_CTRL_REG1, ctrl1)) return false;

  // 配置CTRL_REG4(量程+分辨率)
  uint8_t ctrl4 = fs;
  if (mode == LIS3DH_MODE_NORMAL) ctrl4 |= 0x08;  // 高分辨率位
  if (!write_reg(dev, LIS3DH_REG_CTRL_REG4, ctrl4)) return false;

  // 更新设备状态
  dev->fs = fs;
  dev->mode = mode;
  dev->sensitivity = get_sensitivity(fs, mode);
  return true;
}

// 读取加速度数据(原始值+g值)
bool lis3dh_read_data(lis3dh_dev_t *dev, lis3dh_data_t *data) {
  if (!dev || !data || !dev->initialized) return false;

  // 检查数据就绪(STATUS_REG bit3=1)
  uint8_t status;
  if (!read_reg(dev, LIS3DH_REG_STATUS_REG, &status) || !(status & 0x08)) {
    return false;  // 数据未就绪
  }

  // 读6字节加速度数据(X_L, X_H, Y_L, Y_H, Z_L, Z_H)
  uint8_t buf[6];
  if (!read_regs(dev, LIS3DH_REG_OUT_X_L, buf, 6)) return false;

  // 组合16位数据(小端格式)
  data->x = (int16_t)((buf[1] << 8) | buf[0]);
  data->y = (int16_t)((buf[3] << 8) | buf[2]);
  data->z = (int16_t)((buf[5] << 8) | buf[4]);

  // 转换为g值(1g=1000mg)
  data->x_g = (float)data->x * dev->sensitivity / 1000.0f;
  data->y_g = (float)data->y * dev->sensitivity / 1000.0f;
  data->z_g = (float)data->z * dev->sensitivity / 1000.0f;
  return true;
}

// 进入低功耗模式(掉电,仅保留寄存器配置)
bool lis3dh_enter_low_power(lis3dh_dev_t *dev) {
  if (!dev || !dev->initialized) return false;
  // 设置CTRL_REG1为0x00(ODR=0,所有轴关闭)
  return write_reg(dev, LIS3DH_REG_CTRL_REG1, 0x00);
}

// 唤醒传感器(设置ODR并启动测量)
bool lis3dh_wakeup(lis3dh_dev_t *dev, lis3dh_odr_t odr) {
  if (!dev || !dev->initialized) return false;
  // 配置CTRL_REG1(ODR+使能三轴)
  uint8_t ctrl1 = odr | 0x07;  // 0x07=使能X/Y/Z轴
  if (dev->mode == LIS3DH_MODE_LOW_POWER) ctrl1 |= 0x08;  // 低功耗位
  return write_reg(dev, LIS3DH_REG_CTRL_REG1, ctrl1);
}

// 配置单击检测(中断1唤醒MCU)
bool lis3dh_config_click(lis3dh_dev_t *dev, uint8_t threshold, uint8_t duration) {
  if (!dev || !dev->initialized) return false;
  // 1. 配置中断1:单击检测(X/Y/Z轴)
  if (!write_reg(dev, LIS3DH_REG_INT1_CFG, 0x2A)) return false;  // 0x2A=Z_HI+Y_HI+X_HI
  // 2. 设置阈值(1LSB=灵敏度,如2g量程下1LSB=16mg@低功耗)
  if (!write_reg(dev, LIS3DH_REG_INT1_THS, threshold)) return false;
  // 3. 设置持续时间(1LSB=1/ODR,如100Hz下1LSB=10ms)
  if (!write_reg(dev, LIS3DH_REG_INT1_DUR, duration)) return false;
  // 4. 使能中断1(CTRL_REG3 bit6=1)
  return write_reg(dev, LIS3DH_REG_CTRL_REG3, 0x40);
}

2.3 平台适配层(以STM32 HAL库为例)

c 复制代码
// platform_i2c.c(用户需根据硬件修改)
#include "lis3dh.h"
#include "stm32f1xx_hal.h"  // 替换为实际MCU头文件

extern I2C_HandleTypeDef hi2c1;  // I2C句柄(需在CubeMX中配置)

// I2C写函数(STM32 HAL库实现)
bool i2c_write(uint8_t addr, uint8_t reg, uint8_t data) {
  return HAL_I2C_Mem_Write(&hi2c1, addr<<1, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 100) == HAL_OK;
}

// I2C读函数(STM32 HAL库实现)
bool i2c_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
  return HAL_I2C_Mem_Read(&hi2c1, addr<<1, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 100) == HAL_OK;
}

// 延时函数(STM32 HAL库实现)
void delay_ms(uint32_t ms) {
  HAL_Delay(ms);
}

三、低功耗应用示例(STM32 + 电池供电)

c 复制代码
// main.c(低功耗场景:电池供电,事件驱动唤醒)
#include "lis3dh.h"
#include "stm32f1xx_hal.h"

lis3dh_dev_t accel = {0};

int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_I2C1_Init();  // 初始化I2C(CubeMX配置)

  // 1. 初始化传感器
  if (!lis3dh_init(&accel, LIS3DH_I2C_ADDR)) {
    Error_Handler();  // 传感器初始化失败
  }

  // 2. 配置低功耗参数(1Hz ODR,±2g量程,低功耗模式)
  lis3dh_config(&accel, LIS3DH_ODR_1HZ, LIS3DH_FS_2G, LIS3DH_MODE_LOW_POWER);

  // 3. 配置单击检测(阈值=20mg@低功耗模式,持续时间=10ms)
  lis3dh_config_click(&accel, 1, 1);  // 阈值=1LSB=16mg,持续1个ODR周期(1s@1Hz)

  while (1) {
    // 4. 进入低功耗模式(仅保留传感器中断唤醒)
    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    
    // 5. 唤醒后读取数据(中断触发时执行)
    lis3dh_data_t data;
    if (lis3dh_read_data(&accel, &data)) {
      // 处理数据(如通过BLE发送)
    }
  }
}

参考代码 低功耗加速度传感器LIS3DH芯片的源程序 www.youwenfan.com/contentcsu/56259.html

四、关键低功耗设计说明

  1. 模式切换 :通过lis3dh_enter_low_power()进入掉电模式(2μA),lis3dh_wakeup()唤醒并设置ODR(1Hz时功耗~2.5μA)。

  2. 事件驱动:配置单击/自由落体中断,传感器检测到事件时触发INT1引脚,唤醒MCU(避免轮询)。

  3. 参数优化:低功耗模式下使用8位分辨率(灵敏度16mg/LSB@±2g),降低数据量;1Hz ODR减少采样频率。

五、使用注意事项

  • I2C地址:根据SDO引脚电平选择0x18(接地)或0x19(接VCC)。

  • 灵敏度计算:低功耗模式(8位)灵敏度=量程/128,正常模式(12位)=量程/4096。

  • 中断配置:INT1引脚需配置为上拉输入,下降沿触发(LIS3DH默认高电平有效)。

相关推荐
木斯佳几秒前
HarmonyOS 6 ArkGraphics 3D精讲:从旋转立方体看鸿蒙原生3D能力
3d·华为·harmonyos
吃好睡好便好9 小时前
在Creo中如何把新建零件文件时的默认模板设置为公制单位
学习·3d·信息可视化
AI浩13 小时前
基于运动对齐RGB与事件视觉线索的无标签长时序3D无人机轨迹预测
3d·无人机
小宇的天下18 小时前
TSMC 3DXF 文件解析
3d
2401_8638014620 小时前
逆向网格stl,fbx,obj格式等转换实体曲面stp,igs格式插件文件小,速度快工具
3d·stp
threelab21 小时前
潮玩DIY设计平台技术解析:基于Babylon.js的3D定制化实践
开发语言·javascript·3d
青稞社区.2 天前
直播预告!面向几何与运动理解的流式前馈 3D/4D 重建
人工智能·3d
·心猿意码·2 天前
OCCT源码解析(六):TKG3d 模块——三维曲面体系
c++·3d
:mnong2 天前
PlayCanvas 开源 WebGL/WebGPU 3D 创作平台分析
3d·开源·webgl
threelab2 天前
Three.js 初中数学函数可视化 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器