ADXL372高g加速度计驱动实战:初始化、FIFO与瞬时开关配置
2026/9/23 16:26:48 网站建设 项目流程

简介:ADI公司的ADXL372三轴加速度计中文版数据手册PDF,面向硬件工程师、嵌入式开发者和物联网产品选型人员,用于解决高g冲击检测场景下的器件选型与驱动开发问题。压缩包内共1个PDF文件,体积17.65MB,为完整中文翻译版数据手册,内容覆盖功能框图、引脚配置、SPI/I2C接口规范、典型性能曲线以及冲击检测、FIFO、唤醒模式等关键章节。已有1029人浏览学习。手册重点阐述了±200g量程、3200Hz输出速率下仅22µA的超低功耗特性,并结合4极抗混叠滤波器、可调高通滤波器、低功耗唤醒和瞬时开启模式,解释了如何在撞击事件发生时既保持微安级功耗又能快速捕获瞬态数据。同时,手册对系统级省电策略、自主中断处理和峰值加速度捕获机制也有详细说明,可直接帮助开发者在资产健康评估、便携式IoT边缘节点、脑震荡检测等产品设计中缩短验证周期。

1. 搜 ADXL372 中文 pdf,其实你要的是这颗高 g 加速度计的初始化顺序

搜「ADXL372中文pdf」的人,多数不是缺那几十页翻译,而是手上有一颗 ADXL372,正接到 STM32 或 ESP32 上,卡在 DEVID 读不对、FIFO 数据顺序怪、瞬时开关节能模式配置不上这类具体问题上。ADXL372 是 ADI 的 ±200 g 三轴 MEMS 加速度计,和常见的 ADXL345 不是一类:量程固定很高、测量功耗约 22 µA、待机约 0.1 µA,还内置 512 字节 FIFO 和超量程检测,适合做撞击记录、跌落检测、工业设备冲击监测。这篇文章把「初始化 → 配置 FIFO → 读数据 → 做撞击检测」整条链路讲完,顺带把中文手册里容易看岔的位置标出来,让新手能按步骤跑通,让熟手少踩两个寄存器级的坑。

2. 先看清 ADXL372 的定位,再选 SPI 或 I2C 接口

2.1 同为三轴加速度计,ADXL345 和 ADXL362 不能平替 ADXL372

ADXL372 出现在手里的原因通常只有一个:要测的东西会「撞」,而且撞得比 ±16 g 狠。ADXL345 的满量程是 ±16 g,日常姿态检测够用,但设备跌落或金属部件碰撞时峰值轻易超过 50 g,量程小的传感器直接削顶,后续所有算法都失去意义。ADXL362 主打微功耗,量程却只有 ±8 g,适合电池供电的倾斜与活动监测,同样接不了冲击信号。ADXL372 的意义在于把「高 g 量程」和「低功耗」放在同一颗芯片里:量程 ±200 g,输出带宽最高到 3.2 kHz 这一档,测量模式典型功耗约 22 µA,待机约 0.1 µA。它和 ADXL345 一样是 12 位 ADC,但设计目标是撞击记录、跌落检测、工业设备冲击监测这类短时大信号场景。

型号量程输出数据速率典型功耗FIFO典型场景
ADXL345±16 g最高 3200 Hz测量约 140 µA32 级姿态、倾斜、运动检测
ADXL362±8 g最高 400 Hz测量约 2 µA @100 Hz512 样本电池供电活动检测
ADXL372±200 g最高 3.2 kHz测量约 22 µA512 字节撞击、跌落、冲击记录

选型时还有一层容易忽略:撞击事件的脉宽可能只有 1 ms,要让峰值不被漏掉,ODR 至少要 1 kHz 以上。ADXL375 也是一颗高 g 芯片,但 ADXL372 的优势在 FIFO 和超量程检测,数据可以不经过主控连续缓存,主控休眠时检测到超阈值再醒来读,对电池供电的监测节点友好得多。

2.2 引脚电平、I2C 地址和上电时序,先于代码确认

拿到 ADXL372 先别急着写驱动,两个引脚问题要先确认。VDD 范围是 2.0~3.5 V,接口电平由 IO_VDD 决定,MCU 是 3.3 V 就接 3.3 V,MCU 是 1.8 V 就接 1.8 V,不能直接把 IO_VDD 悬空。ADDR/SDO 这个引脚在 I2C 模式下决定从机地址的前几位,常见默认地址是 0x1D;在 SPI 模式下它作为 SDO 数据输出复用,所以同一个引脚在两种总线下的角色完全不同。如果之前用过 ADXL345,别想当然沿用它的地址和字节序,寄存器映射并不一样。

上电时序是新人最常见的问题来源。VDD 稳定后芯片需要一小段时间完成内部上电复位,紧接着还要做一次软复位:向寄存器 0x1F 写入 0x52,然后等待至少几毫秒。我一般会读三遍 DEVID(0x00),三次都读到 0xAD 才认为 SPI/I2C 通路正常,三次中任何一次读到 0x00 或 0xFF,先查 CS 时序和 I2C 地址,不要急着调寄存器。

uint8_t adxl372_read_reg(uint8_t reg) { uint8_t tx[2] = { (uint8_t)(reg << 1), 0x00 }; uint8_t rx[2] = { 0 }; cs_low(ADXL372_CS_PIN); spi_transfer(tx, rx, 2); cs_high(ADXL372_CS_PIN); return rx[1]; /* 第一个字节是地址,第二个字节才是数据 */ }

读单字节时,SPI 指令由地址字节本身承载:reg 左移一位,最低位为 0 表示读。这里 addr 是 7 位寄存器地址,所以reg << 1得到完整 8 位指令。CS 拉低后连续传两个字节,第一个字节是地址,第二个字节是芯片回的数据。用同样的方式写寄存器时,把最低位置 1:

void adxl372_write_reg(uint8_t reg, uint8_t val) { uint8_t tx[2] = { (uint8_t)((reg << 1) | 0x01), val }; cs_low(ADXL372_CS_PIN); spi_transfer(tx, NULL, 2); cs_high(ADXL372_CS_PIN); }

SPI 模式用模式 3(CPOL=1、CPHA=1),SCLK 频率按型号手册标注的上限留一半余量,比如手册标 10 MHz,驱动里先设 5 MHz 调通再说。上电后先软复位,再读 DEVID,顺序不能反过来;DEVID 读到 0xAD 后,可以读相邻的 DEVID_MST(0x01)和 PART_ID(0x02)做二次校验,这三字节组合能挡住大部分总线错位问题。

2.3 读 0x08–0x0D 一组完整样本,验证数据通路

只用单字节读也能拿数据,但每个样本 6 字节,逐字节读要发 6 次 CS 周期,FIFO 满时容易漏数据。常见的做法是支持地址自动递增的多字节读:把起始地址发出去后,后续每个时钟直接返回连续寄存器。ADXL372 的输出寄存器组从 0x08 开始,顺序是 XDATA_L、XDATA_H、YDATA_L、YDATA_H、ZDATA_L、ZDATA_H,千万不要把低字节和高字节的顺序写反。

typedef struct { int16_t x; int16_t y; int16_t z; } adxl372_sample_t; adxl372_sample_t adxl372_read_sample(void) { uint8_t buf[6]; adxl372_read_burst(0x08, buf, 6); adxl372_sample_t s; s.x = (int16_t)((buf[0] << 8) | buf[1]) >> 4; s.y = (int16_t)((buf[2] << 8) | buf[3]) >> 4; s.z = (int16_t)((buf[4] << 8) | buf[5]) >> 4; return s; }

寄存器里保存的是 12 位左对齐数据,低 4 位是无效位。把两字节拼成 16 位后右移 4 位,就得到 12 位带符号数,范围约 -2048 到 +2047。这里符号由int16_t自然承接,右移后不需要再手动补符号位。换算成 g 值时,不同型号的标称灵敏度不一样,驱动里通常用一个常量 scale 表示,具体数值按数据手册「芯片属性表」里的灵敏度参数填,不要从别的型号驱动里复制。

到这里数据通路已经能跑通,但离「能测撞击」还差一步:测量模式和 FIFO 还没配置。下面进入正式配置。

3. 测量模式配置:从 DEVID 正确到 FIFO 批量读出

3.1 POWER_CTL 三种模式:待机、测量、瞬时开

寄存器 0x2C(POWER_CTL)的低两位决定芯片工作模式:0b00 是待机,0b01 是测量,0b10 是瞬时开(Instant On),0b11 保留。待机模式下寄存器可读可写,但加速度输出通道不更新,很多「DEVID 正常、数据恒为 0」的问题,最后都发现是忘了写 0x2C。测量模式才是正常输出数据流的模式。瞬时开是给低功耗撞击检测用的,芯片内部保持高速采样以做阈值比较,但不对外输出连续数据流,检测到超阈值后再唤醒主机,具体配置放到第 4 节。

void adxl372_set_measure_mode(void) { adxl372_write_reg(0x2C, 0x01); /* MODE 字段 = 0b01 */ }

写入模式寄存器后,要等一个采样周期数据才有效。ODR 是 1600 Hz 时,等待 1 ms 以上再读即可;ODR 较低时按1000 / ODR毫秒估算。另外,不要在待机模式下测量功耗,那样测的是待机功耗,不是真实工况。

3.2 MEASURE_CTRL 带宽/ODR 与滤波器搭配

寄存器 0x2D(MEASURE_CTRL)负责输出数据速率、带宽和滤波方式。ODR 的选择直接决定能捕捉到多窄的冲击脉冲。撞击事件越短,需要的 ODR 越高;但 ODR 升高后 FIFO 消耗速度也变快,60 个样本在 1600 Hz 下只覆盖 37.5 ms 时间窗。

ODR 档位适用场景60 样本时间窗
200 Hz长时趋势监测、慢冲击300 ms
800 Hz一般碰撞、1~2 ms 脉宽75 ms
1600 Hz短脉冲、尖峰捕捉37.5 ms
3200 Hz极短冲击、需要看峰值细节18.75 ms

滤波搭配上,金属碰撞往往伴随高频振铃,如果只关心冲击包络,打开低通滤波器把振铃滤掉;如果要检测的方向包含静态重力分量,比如设备从水平桌面跌落,还要考虑交流耦合或高通滤波,否则 1 g 重力叠加在 ±200 g 量程上,虽然量程冗余很大,但会影响阈值判断的基线。具体 ODR 和滤波器的位域组合,以数据手册 MEASURE_CTRL 章节的表格为准,因为不同版本手册对不同 ODR 档位的编码有调整,抄旧代码容易踩坑。

3.3 FIFO 模式和水位线:别把旁路模式当 FIFO 用

FIFO 控制寄存器是 0x18,高两位选 FIFO 模式,低六位配置水位线。四种模式差别很大:旁路模式相当于不用 FIFO,读寄存器直通;FIFO 模式填满指定水位后停止写入,适合事件发生后一次性读出;流式模式填满后覆盖最旧数据,适合持续监测最后 N 个样本;触发模式由触发条件决定保存哪些样本。想做撞击记录一般用 FIFO 模式,想抓撞击前的背景用流式或触发模式。

模式行为典型用法
00 旁路不缓存,直接读寄存器数据直通、调试
01 FIFO装满即停撞击后读一次
10 流式覆盖最旧持续监测最后 N 样本
11 触发按触发条件存事件前后对比

FIFO 物理容量是 512 字节,每样本 6 字节,理论上能存 85 个样本。但水位线字段只有 6 位,最大值 63,不能直接配到 85。碰上要等 FIFO 几乎满时才读的场景,我一般把水位配到 60,然后轮询 FIFO_ENTRIES(0x12/0x13,12 位样本计数)判断实际样本数。

#define FIFO_WATERMARK 60u /* 水位上限 63,这里取 60 */ void adxl372_fifo_config(void) { uint8_t ctrl = (0x01u << 6) | (FIFO_WATERMARK & 0x3Fu); adxl372_write_reg(0x18, ctrl); }

高位置 0b01 表示 FIFO 模式,低六位是水位。FIFO 模式在样本数达到水位后停止写入,主机读取 FIFO_DATA 后样本计数递减,FIFO 随之腾出空间。如果配的是流式模式,达到水位后不会停,而是继续覆盖最旧样本,所以流式场景下水位更像「告警线」而不是「停止线」。

uint16_t adxl372_fifo_entries(void) { uint8_t l = adxl372_read_reg(0x12); uint8_t h = adxl372_read_reg(0x13); return (uint16_t)(((h & 0x07) << 8) | l); } void adxl372_fifo_read_all(uint8_t *buf, uint16_t max_samples) { uint16_t n = adxl372_fifo_entries(); if (n > max_samples) { n = max_samples; } adxl372_read_burst(0x11, buf, n * 6u); }

FIFO_ENTRIES 高寄存器只有低 3 位有效,所以h & 0x07不能省。批量读时起始地址用 0x11(FIFO_DATA),连续读 6N 字节,每 6 字节按 X_L、X_H、Y_L、Y_H、Z_L、Z_H 排列,和输出寄存器组的顺序一致。读完 FIFO 后如果还想继续用 FIFO,不需要重新写 0x18,样本消耗后自动继续工作;但如果在 FIFO 模式停下来没读完,新数据不会自动补进来,这是 FIFO 模式与流式模式的行为差异。

3.4 用 Python 解析原始 FIFO 字节流,快速验证波形

拿到 FIFO 原始字节后,先用 Python 解析一版,比在嵌入式端反复改打印效率高。下面的函数输入整段 FIFO 字节流,输出每轴的 g 值列表。

def parse_fifo(blob: bytes, scale: float = 0.049): samples = [] for i in range(0, len(blob) - 5, 6): axes = [] for j in range(3): lo = blob[i + j * 2] hi = blob[i + j * 2 + 1] v = (lo << 8) | hi v >>= 4 if v >= 2048: v -= 4096 axes.append(v * scale) samples.append(tuple(axes)) return samples

scale是灵敏度系数,单位 g/LSB,示例值 0.049 仅用于演示,投产后以手册标称值和实际翻转测量为准。v >>= 4之后得到 12 位带符号数,范围 -2048~+2047,再对大于等于 2048 的值减 4096 完成符号修正。解析结果如果看到 X 轴敲击却出现在 Y 轴,优先怀疑字节序或三轴映射,而不是传感器坏了。把解析出的列表画成曲线,能直接看到撞击包络、振铃以及 FIFO 是否覆盖了完整事件。

4. 用瞬时开关做低功耗撞击检测,附三个高频排错点

4.1 瞬时开关:平时不输出数据,超阈值才唤醒

如果设备靠电池供电,测量模式 22 µA 的功耗在许多场景下仍然偏高。瞬时开模式是 ADXL372 比较有特点的用法:芯片内部保持高速采样,检测到超过阈值的加速度后,通过 INT 引脚唤醒主控,主控从睡眠中醒来再把 FIFO 里的数据读走。这个模式下主机不需要持续读取数据流,功耗远低于连读模式。配置顺序很重要,要先配 FIFO、先配阈值,最后再把 POWER_CTL 的模式位切到瞬时开,否则阈值没有生效就切过去,芯片检测不到你想让它醒来的信号。

void adxl372_start_instant_on(void) { adxl372_fifo_config(); /* 先配 FIFO 模式和水位 */ adxl372_set_overrange_threshold(40); /* 超量程阈值,单位按手册换算 */ adxl372_set_measure_mode(); /* 先回测量模式做最后校准 */ adxl372_write_reg(0x2C, 0x02); /* 再切瞬时开模式 */ }

当阈值设定为 40 g 时,芯片内部以较高采样率持续比较,一旦某一轴超过阈值就产生唤醒条件。外部 MCU 进睡眠前确保 INT 引脚已配置为唤醒源;唤醒后先切回测量模式(0x2C=0x01)再读 FIFO,避免在瞬时开模式下读到不完整的数据流。超量程阈值所在的寄存器组请按数据手册「超量程检测」一节查表,不同版本的地址位定义有过调整,写驱动时以手册最新 Rev 的位域名为准。

void adxl372_wakeup_handler(void) { uint8_t buf[6 * FIFO_WATERMARK]; adxl372_write_reg(0x2C, 0x01); /* 切回测量模式 */ adxl372_fifo_read_all(buf, FIFO_WATERMARK); }

4.2 三个高频坑:字节序、复位延时、中文手册版本

第一个坑是 FIFO 内字节序。寄存器组和 FIFO 输出都是 X_L、X_H 一组,很多从 ADXL345 工程迁移过来的代码习惯先读高字节后读低字节,导致数值出现奇怪的横向跳变。第二个坑是软复位后不等待。复位寄存器写入 0x52 后立刻读 DEVID,偶尔能读到 0xAD,但在低 SCLK 和某些 SPI 时序下会读到 0x00,建议复位后延时 5 ms 再做三次一致性校验。第三个坑和这篇标题直接相关:中文 PDF 版本可能滞后于英文最新版,寄存器位定义在小版本升级后有调整,中文版适合理解功能和概念,但做寄存器级开发、特别是涉及 FIFO 和瞬时开这类复杂功能时,以英文原版最新 Revision 为准。

/* 稳定的初始化开头,按顺序执行 */ adxl372_write_reg(0x1F, 0x52); /* 软复位 */ delay_ms(5); for (int i = 0; i < 3; i++) { if (adxl372_read_reg(0x00) != 0xAD) { /* 三次都通过再继续,否则先查总线 */ } }

4.3 静止、翻转、敲击三步,验证整条链路

驱动写完别急着接真实设备,先在桌面上做三个动作。静止平放时,水平两轴读数应在 0 g 附近,竖直轴应接近 ±1 g;翻转设备,竖直轴的符号应该跟着变,这一步能同时验证字节序和量程方向。最后用笔帽或小螺丝刀轻轻敲击桌面,观察读数是否出现明显尖峰。

for _ in range(30): x, y, z = read_one_sample() print(f"X={x:+.2f}g Y={y:+.2f}g Z={z:+.2f}g")

如果敲击时读数始终在 ±1 g 附近,先查阈值是否写进了超量程检测对应的寄存器,而不是误写进了活动检测寄存器组;如果 INT 引脚没拉低,用逻辑分析仪抓一下写入 0x2C 后的寄存器回读值,确认芯片真的处于瞬时开模式。三个动作全部通过后,这套初始化代码就可以移到正式产品里跑了。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询