STM32驱动LIS2DH12三轴加速度计:IIC通信、寄存器配置与中断处理实战

发布时间:2026/10/19 8:42:06
STM32驱动LIS2DH12三轴加速度计:IIC通信、寄存器配置与中断处理实战 简介这份资源面向使用STM32开发运动感知功能的嵌入式工程师与学习者提供LIS2DH12三轴加速度计的IIC通信驱动程序可解决传感器初始化、寄存器配置与数据读取等底层驱动问题适用于移动设备、物联网终端及健康监测等场景。压缩包共8个文件以4个c源文件与4个h头文件为主分别承载IIC通信逻辑、LIS2DH12寄存器操作、外部中断处理及接口声明整体约6KB结构精简便于直接移植。目前已有4560人学习下载。内容覆盖IIC接口初始化、工作模式与采样率配置、加速度原始数据解码为g值、跌落与6D运动等事件检测及中断服务处理并涉及错误检查与DMA传输思路标签中提及的LIS3DH12、BMA250也可作为同类传感器驱动参考帮助读者快速搭建可复用的驱动框架。1. 从一块“哑巴”传感器说起LIS2DH12 到底能帮你做什么如果你手头有一块 STM32 的板子想加个“感知倾斜、检测震动、判断运动方向”的功能大概率会碰到 LIS2DH12 这颗三轴加速度计。它便宜、好焊、功耗低但刚上手时最让人头疼的不是算法而是它只认 IIC 或 SPI寄存器又多又碎数据手册翻半天才能把 WHO_AM_I 读对。我见过不少项目卡在第一步IIC 地址写错、寄存器配置顺序不对、FIFO 读出来全是 0。这份驱动资源就是冲着这些坑来的——它把 LIS2DH12 在 STM32 上的 IIC 通信、初始化配置、数据读取和中断处理都封装好了你拿过去改改引脚和时钟就能跑。适合谁正在做姿态检测、跌倒报警、震动记录、低功耗运动唤醒的嵌入式开发者尤其是用 HAL 库但不想从零啃寄存器的人。下面我按“先跑通、再拆解、最后改”的顺序把这份驱动从接线到二次开发讲透。2. 硬件连接与工程搭建从零把 LIS2DH12 挂上 IIC 总线2.1 引脚接线与上拉电阻的硬性要求LIS2DH12 支持 IIC 和 SPI 两种模式靠 CS 引脚电平决定。接 IIC 时CS 必须拉高到 VDD_IO否则芯片会进入 SPI 模式你发什么它都不理。SCL 和 SDA 各接一个 4.7k 上拉到 VDD_IO这是 IIC 总线的常规操作但很多人用 STM32 内部上拉就偷懒不焊外部电阻结果在 400kHz 速率下波形上升沿塌得厉害读出来的 WHO_AM_I 时对时错。我一般会在 PCB 上留外部上拉的位置调试阶段先用 4.7k稳定后再看能不能省。供电方面VDD 和 VDD_IO 可以都接 3.3V但如果你要和 1.8V 的 MCU 通信VDD_IO 就得单独接 1.8V否则 IIC 电平不匹配会烧引脚。SA0 引脚决定 IIC 从机地址的最低位SA0 接地时地址是 0x18接 VDD_IO 时是 0x19。这个地址是 7 位格式HAL 库调用时要左移一位变成 8 位。我见过有人直接写 0x18 给 HAL结果 HAL 内部又移了一次地址变成 0x30死活读不到数据。/* LIS2DH12 IIC 地址定义SA0 接地为 0x18接 VDD 为 0x19 */ #define LIS2DH12_IIC_ADDR_7BIT 0x18 #define LIS2DH12_IIC_ADDR_8BIT (LIS2DH12_IIC_ADDR_7BIT 1) /* STM32 HAL 库使用的地址格式 */ #define LIS2DH12_HAL_ADDR LIS2DH12_IIC_ADDR_8BIT上面这段地址定义看着简单但参数说明得清楚LIS2DH12_IIC_ADDR_7BIT是数据手册里的从机地址LIS2DH12_IIC_ADDR_8BIT是左移一位后的写地址HAL 库的HAL_I2C_Mem_Read函数要求传入的就是这个 8 位格式。如果你用软件模拟 IIC那就要自己按 7 位地址加读写位拼字节别混用。2.2 STM32CubeMX 配置 IIC 外设与工程骨架用 CubeMX 配置 IIC 最快。选好对应的 IIC 外设速度模式设成 Fast Mode 400kHz时钟源用 PCLK1。注意 IIC 的时钟频率不能超过 400kHzLIS2DH12 在高速模式下虽然支持 400kHz但如果你走线长、上拉弱建议先降到 100kHz 调通再提速。DMA 可以不开加速度数据量不大轮询或中断都够用。生成工程后目录结构一般是这样的Project/ ├── Core/ │ ├── Inc/ │ │ ├── lis2dh12.h // 驱动头文件寄存器定义和函数声明 │ │ └── main.h │ └── Src/ │ ├── lis2dh12.c // 驱动实现IIC 读写和配置逻辑 │ └── main.c ├── Drivers/ │ └── STM32F1xx_HAL_Driver/ └── MDK-ARM/ 或 STM32CubeIDE/把lis2dh12.c和lis2dh12.h放进 Core 目录在 main.c 里包含头文件就能调用。我习惯把驱动独立成一对文件不往 main.c 里塞寄存器操作后面换 MCU 或换 IIC 外设时只改驱动里的底层读写函数上层逻辑不动。2.3 底层 IIC 读写函数的封装驱动能不能移植全看底层读写函数抽得干不干净。这份驱动里我把 IIC 读写封装成两个静态函数上层只调lis2dh12_read_reg和lis2dh12_write_reg。/** * brief 读取 LIS2DH12 单个寄存器 * param reg_addr: 寄存器地址 * param p_data: 存放读出数据的缓冲区 * retval HAL 状态 */ static HAL_StatusTypeDef lis2dh12_read_reg(uint8_t reg_addr, uint8_t *p_data) { return HAL_I2C_Mem_Read(hi2c1, LIS2DH12_HAL_ADDR, reg_addr, I2C_MEMADD_SIZE_8BIT, p_data, 1, 100); } /** * brief 写入 LIS2DH12 单个寄存器 * param reg_addr: 寄存器地址 * param data: 待写入的数据 * retval HAL 状态 */ static HAL_StatusTypeDef lis2dh12_write_reg(uint8_t reg_addr, uint8_t data) { return HAL_I2C_Mem_Write(hi2c1, LIS2DH12_HAL_ADDR, reg_addr, I2C_MEMADD_SIZE_8BIT, data, 1, 100); }逻辑说明HAL_I2C_Mem_Read的第二个参数是从机地址必须是 8 位格式第三个参数是寄存器地址第四个参数I2C_MEMADD_SIZE_8BIT表示寄存器地址是 8 位宽LIS2DH12 所有寄存器地址都是 8 位别选成 16 位。最后一个参数是超时时间单位毫秒100ms 足够。如果你用软件 IIC就把这两个函数体换成自己的 GPIO 翻转逻辑上层初始化流程完全不用动。3. 寄存器配置与数据读取把加速度值从黑匣子里捞出来3.1 初始化流程WHO_AM_I 校验与 CTRL_REG 配置顺序LIS2DH12 上电后默认是掉电模式所有配置都得在唤醒前写好。初始化第一步是读WHO_AM_I寄存器地址 0x0F正常返回值是 0x33。这一步不能省我踩过坑板子上焊的是 LIS3DH寄存器兼容但 WHO_AM_I 返回 0x33 以外的值如果不校验后面读出来的数据量程对不上算法全乱。/** * brief 初始化 LIS2DH12 * retval 0 成功-1 失败 */ int8_t lis2dh12_init(void) { uint8_t who_am_i 0; /* 1. 校验 WHO_AM_I */ if (lis2dh12_read_reg(LIS2DH12_WHO_AM_I, who_am_i) ! HAL_OK) { return -1; } if (who_am_i ! LIS2DH12_WHO_AM_I_VALUE) { return -1; } /* 2. 软复位等待复位完成 */ lis2dh12_write_reg(LIS2DH12_CTRL_REG5, 0x80); HAL_Delay(10); /* 3. 配置 CTRL_REG1100Hz 输出速率XYZ 使能 */ lis2dh12_write_reg(LIS2DH12_CTRL_REG1, 0x57); /* 4. 配置 CTRL_REG4±2g 量程高分辨率模式 */ lis2dh12_write_reg(LIS2DH12_CTRL_REG4, 0x08); /* 5. 配置 CTRL_REG3使能 INT1 中断 */ lis2dh12_write_reg(LIS2DH12_CTRL_REG3, 0x40); return 0; }参数说明CTRL_REG1写 0x57二进制是 0101 0111低三位是 XYZ 使能位全 1 表示三轴都开第四位是低功耗模式位0 表示正常模式高四位 0101 对应 100Hz 输出速率。CTRL_REG4写 0x08bit3 置 1 表示高分辨率模式bit4 和 bit5 是量程选择00 对应 ±2g。如果你要测更大的震动改成 ±4g 就把 bit4 置 1写 0x18。CTRL_REG3写 0x40 是把 INT1 中断映射到 AOI1 引脚后面做运动唤醒会用到。3.2 读取三轴加速度OUT_X_L 到 OUT_Z_H 的连续读LIS2DH12 的加速度数据放在 0x28 到 0x2D 六个寄存器里低字节在前高字节在后。读的时候用连续读一次把六个字节全捞出来避免中间被新数据覆盖。/** * brief 读取三轴加速度原始值 * param p_raw: 存放原始数据的数组顺序为 X_L, X_H, Y_L, Y_H, Z_L, Z_H * retval HAL 状态 */ HAL_StatusTypeDef lis2dh12_read_raw(int16_t *p_raw) { uint8_t buf[6] {0}; if (HAL_I2C_Mem_Read(hi2c1, LIS2DH12_HAL_ADDR, LIS2DH12_OUT_X_L | 0x80, /* 0x80 表示地址自动递增 */ I2C_MEMADD_SIZE_8BIT, buf, 6, 100) ! HAL_OK) { return HAL_ERROR; } p_raw[0] (int16_t)((buf[1] 8) | buf[0]); /* X 轴 */ p_raw[1] (int16_t)((buf[3] 8) | buf[2]); /* Y 轴 */ p_raw[2] (int16_t)((buf[5] 8) | buf[4]); /* Z 轴 */ return HAL_OK; }逻辑说明寄存器地址或上 0x80 是 LIS2DH12 的地址自动递增标志这样读第一个字节后地址自动加一连续读六个不用反复发起始条件。合成 16 位数据时低字节在前所以是(buf[1] 8) | buf[0]。原始值转成实际加速度的公式是加速度 原始值 * 量程 / 32768。±2g 量程下灵敏度是 1mg/digit原始值除以 1000 就是 g 值。如果你开了高分辨率模式灵敏度会变具体看数据手册的灵敏度表。3.3 FIFO 与中断配置做低功耗运动唤醒的关键如果你要做“平时休眠、震动时唤醒”的功能FIFO 和中断必须配好。LIS2DH12 的 FIFO 有 32 级可以设成 Stream 模式或 FIFO 模式。我一般用 Stream 模式FIFO 满了之后新数据覆盖旧数据读的时候一次把水印级别以上的数据全读走。/** * brief 配置 FIFO 和中断用于运动唤醒 */ void lis2dh12_config_fifo_int(void) { /* FIFO_CTRL_REGStream 模式水印级别 16 */ lis2dh12_write_reg(LIS2DH12_FIFO_CTRL_REG, 0x80 | 16); /* CTRL_REG3INT1 使能 FIFO 水印中断 */ lis2dh12_write_reg(LIS2DH12_CTRL_REG3, 0x04); /* INT1_CFG使能 X/Y/Z 高事件中断 */ lis2dh12_write_reg(LIS2DH12_INT1_CFG, 0x2A); /* INT1_THS阈值设为 0x10约 256mg */ lis2dh12_write_reg(LIS2DH12_INT1_THS, 0x10); /* INT1_DURATION持续时间设为 0x02避免抖动误触发 */ lis2dh12_write_reg(LIS2DH12_INT1_DURATION, 0x02); }参数说明FIFO_CTRL_REG高两位是 FIFO 模式10 表示 Stream 模式低五位是水印级别写 16 表示 FIFO 里攒够 16 个数据就触发中断。INT1_CFG写 0x2A二进制 0010 1010bit1 和 bit3 和 bit5 分别对应 X、Y、Z 的高事件使能bit7 是中断使能位。INT1_THS是阈值单位是 16mg/digit写 0x10 就是 256mg低于这个加速度不触发。INT1_DURATION是持续时间单位是输出速率周期写 0x02 表示连续两个周期都超过阈值才触发能滤掉单次抖动。4. 避坑与常见问题IIC 读不到数据时先查这几处4.1 现象WHO_AM_I 读出来是 0x00 或 0xFF原因IIC 总线没通。先量 SCL 和 SDA 的静态电平正常应该是高电平。如果一直是低检查上拉电阻是否焊了、阻值是否太大。如果电平正常但读不到用逻辑分析仪抓波形看从机地址有没有应答位。常见错误是地址左移方向搞反或者 CS 引脚没拉高导致芯片进了 SPI 模式。解决确认 CS 接 VDD_IOSA0 接地时用 0x18 左移一位得 0x30 给 HAL。如果还不行把 IIC 速率降到 100kHz 再试有些便宜模块的上拉电阻是 10k400kHz 下上升沿太慢。4.2 现象数据能读但三轴值全是 0原因CTRL_REG1 没配置对芯片还在掉电模式。LIS2DH12 上电默认是 0000 0000XYZ 都没使能输出寄存器一直是 0。解决检查lis2dh12_init里有没有写CTRL_REG1写完之后延时 10ms 再读数据。另外确认CTRL_REG4的 BDU 位有没有置 1如果没置 1读数据时高低字节可能来自不同采样周期数据会跳变。4.3 现象静止时 Z 轴读数在 1000 左右跳动不是稳定的 1g原因量程和灵敏度没对齐。±2g 量程下静止时 Z 轴应该读到约 10001g 1000mg但如果你开了高分辨率模式灵敏度变成 1mg/digit 还是 2mg/digit 要看具体配置。另外电源纹波大也会导致读数跳动。解决先确认CTRL_REG4的 HR 位和 FS 位对照数据手册的灵敏度表算实际值。电源引脚并一个 100nF 和 10uF 电容LIS2DH12 对电源噪声比较敏感。4.4 现象中断引脚一直不触发原因中断阈值设太高或者中断没映射到对应的引脚。LIS2DH12 的 INT1 和 INT2 是分开配置的CTRL_REG3控制 INT1 的中断源CTRL_REG6控制 INT2。解决先把阈值降到 0x05 试触发确认中断通路没问题再往上加。用万用表量 INT1 引脚触发时应该有电平变化。如果用的是开漏输出记得接上拉电阻。4.5 现象FIFO 读出来的数据顺序错乱原因读 FIFO 时没有用连续读或者读的字节数和 FIFO 里的数据量不匹配。LIS2DH12 的 FIFO 数据从OUT_X_L开始每次读六个字节为一组。解决先读FIFO_SRC_REG看 FIFO 里有多少组数据然后一次性连续读组数 * 6个字节。读的时候地址要或上 0x80 开启自动递增否则读来读去都是同一个寄存器。5. 二次开发改造换量程、换速率、换 MCU 的实操思路拿到这份驱动后最常改的三个地方是量程、输出速率和底层 IIC 接口。先说量程。如果你要测跌倒或碰撞±2g 很容易饱和改成 ±16g 只需要动CTRL_REG4的 bit4 和 bit5。写 0x38 就是 ±16g 加高分辨率但注意高分辨率模式下 ±16g 的灵敏度是 12mg/digit换算公式里的分母要跟着变。我一般会在头文件里定义一个LIS2DH12_SENSITIVITY_MG宏初始化时根据量程赋值读数据时统一乘这个宏避免到处改数字。输出速率在CTRL_REG1的高四位100Hz 是 0101改成 400Hz 就是 0111写 0x77。速率越高功耗越大如果是电池供电的项目建议用 10Hz 或 25Hz配合中断唤醒平时 MCU 休眠有震动再起来读数据。这里有个血泪经验改速率之后INT1_DURATION的时间基准也跟着变原来 100Hz 下写 0x02 是 20ms改成 400Hz 就变成 5ms滤抖效果差很多得同步调大。换 MCU 的场景更常见。如果你从 STM32F1 换到 F4 或 G0HAL 库的 IIC 句柄名字可能从hi2c1变成hi2c2底层读写函数里的句柄参数改一下就行。如果是换成软件 IIC把lis2dh12_read_reg和lis2dh12_write_reg两个函数体替换成 GPIO 模拟时序上层初始化、读数据、配中断的代码一行不用动。我习惯在驱动头文件里留一个LIS2DH12_USE_HARDWARE_IIC的宏编译时选择走 HAL 还是走软件模拟移植时省事。验证改造是否成功我一般分三步第一步读WHO_AM_I确认通信正常第二步静止放置看三轴读数是否稳定在 0、0、1000 附近第三步晃动传感器看数据是否跟着变中断引脚是否触发。这三步过了基本就能进算法层了。从那以后我每次改完量程或速率都强制走一遍这三步验证不然算法调半天才发现是驱动配置错了后悔药都没地方买。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询