ADXL355三轴加速度计开发指南:从SPI读取到振动监测
2026/9/16 1:35:18 网站建设 项目流程

简介:面向STM32开发者与嵌入式入门者的ADXL355加速度传感器资料包,聚焦于使用HAL库通过SPI接口驱动ADXL355,完成简单计步器设计。资源内容涵盖传感器硬件设计所需的原理图、装配图、物料清单与Gerber制板文件,同时提供SPI驱动及计步功能参考代码,可帮助读者从电路搭建到程序调试快速搭建一套可运行的加速度检测系统。压缩包整体约27.39MB,文件以PDF、Excel、Gerber及工程代码等类型为主,结构清晰,便于按模块查阅。已有834人学习下载,适合正在学习STM32外设驱动、SPI通信协议或加速度传感器应用的工程技术人员。借助全套资料,能够理解ADXL355三轴加速度数据的读取与滤波处理流程,并掌握如何基于HAL库配置SPI、设计计步逻辑,为后续更复杂的运动检测项目提供可复用的基础方案。

1. ADXL355资料包到手后,先弄清楚这片传感器能干什么

对于做振动监测、倾斜测量或地震前兆研究的工程师来说,ADXL355 是一个绕不开的选择:这是一颗基于 MEMS 电容原理的三轴加速度计,最大的特点是超低噪声密度(在 4g 量程下约为 200 ng/√Hz 级别)、极低的温度漂移,以及内置的 20 位 ADC。和常见的 ADXL345 相比,它省去了外部 ADC 和滤波电路,直接通过 SPI 或 I2C 输出数字量,适合长时间无人值守采集场景,例如桥梁健康监测、风机塔筒振动、工业设备预测性维护等。拿到“ADXL355相关资料.zip”这份压缩包的人,通常不是单纯想点个灯,而是要在一个具体项目里把数据稳定地采回来、算出去。因此,解开这个 zip 之后的第一步,不是急着焊板子,而是先把资料分类理清,再按「硬件连接 → 寄存器配置 → 数据读取 → 参数调优」这条链路推进。下面这套方法,都是我在几个实际项目里反复验证过的,你可以直接套用。

2. 解开ADXL355压缩包后,先整理资料类型和选型清单

2.1 压缩包内的资料通常分为五类,别在数据手册上死磕

从经验看,一份完整的 ADXL355 资料 zip 包里,一般包含数据手册(PDF)、寄存器映射表、示例代码(C 或 Arduino)、参考原理图和 PCB 封装库,外加一些应用笔记。很多人习惯一上来就把 40 多页的英文数据手册从头读到尾,其实效率很低。我一般会先按以下顺序快速浏览:

  • 先看寄存器映射表,找到REG_DEVICE_ID(地址 0x00),用于后续验证 SPI/I2C 通信是否正常。
  • 再看POWER_CTL(地址 0x2D)和RANGE(地址 0x2C)这两个寄存器的默认值和配置位。
  • 最后看时序图,确认 SPI 模式下支持的最高时钟频率是 10 MHz,I2C 是 400 kHz。

如果是基于单片机(比如 STM32、ESP32)做开发,参考原理图价值最大,能直接告诉你去耦电容的选型——ADXL355 的 VDD 和 VDDIO 都需要 0.1 μF 和 1 μF 的组合电容,且 1 μF 必须靠近芯片引脚。这个细节如果忽略,高速采样时数据容易出现偶发跳变。

2.2 选型对比:ADXL355并不适合所有振动场景

ADXL355 的优势在于低噪声和低漂移,但它的带宽上限只有约 1 kHz,采样率最高 4000 SPS,且内部数字滤波器的截止频率在最高采样率下只有 500 Hz 左右。这意味着它适合监测 0.1 Hz 到几百 Hz 的振动信号,例如结构物固有频率、旋转机械的转频及倍频。如果是齿轮箱的啮合频率(往往几千赫兹以上),应改用 IEPE 压电传感器或 ADXL1002 这类宽带加速度计。

在选型确认阶段,还要注意量程匹配。ADXL355 可选 ±2g、±4g、±8g,很多人在静态倾角测量里选了 ±2g 以获得更高分辨率,但忽略了安装时的冲击可能超过量程导致数据削顶。建议至少留 2 倍余量:预估最大振动幅值 1.5g 的场合就用 ±4g,而不是 ±2g。

提示:解压资料包后,先确认里面有没有「寄存器速查表」这类单独文档。如果没有,建议自己把常用寄存器地址和默认值整理成一页纸,调试时能省一半时间。

2.3 使用 Python 脚本验证资料包完整性

如果你是第一次从网上下载这份资料,建议先校验一下文件是否完整,避免解压到一半发现示例代码损坏。在 Windows 的 PowerShell 里可以这样操作:

Get-FileHash .\ADXL355相关资料.zip -Algorithm SHA256 tar -tf .\ADXL355相关资料.zip

Get-FileHash计算出的哈希值可以同发布者给出的值比对,tar -tf则能列出 zip 包内的文件清单而不解压,快速确认是否有「examples」或「schematic」目录。在 macOS 或 Linux 下,对应的命令是:

shasum -a 256 ADXL355相关资料.zip unzip -l ADXL355相关资料.zip

注意,unzip -l只能看文件列表,不会真正解压,这对大 zip 包很友好。确认文件齐全后,再解压到工作目录。

3. 快速跑通 ADXL355 SPI 读取:从连线到拿到原始数据

3.1 硬件连接和最小系统搭建

ADXL355 支持 4 线 SPI 和 I2C,但实际项目里绝大多数人用 SPI,因为吞吐量更高且时序可控。接线时关注 8 个引脚:

引脚名功能连接目标
VDD主电源 2.25V~3.6V3.3V
VDDIOIO 口电源3.3V(必须与 MCU 一致)
CS片选MCU GPIO(软件控制)
SCLKSPI 时钟MCU SPI_SCK
MOSI主机输出MCU SPI_MOSI
MISO主机输入MCU SPI_MISO
INT1数据就绪中断可选,接 MCU 外部中断
GND公共地

这里有个容易踩的坑:VDDIO 如果比 MCU 的 GPIO 电压低,MOSI 的高电平可能超过芯片允许范围,导致寄存器写入失效。常见做法是 VDD 和 VDDIO 都接 3.3V,并共用同一条电源轨。在 VDD 引脚附近放 1 μF 和 0.1 μF 去耦电容,GND 用大面积铺铜连接。

SPI 模式选择 Mode 0(CPOL=0,CPHA=0)。MCU 作为主机,时钟频率建议从 1 MHz 起步调试,稳定后再逐步提高到 10 MHz。ADXL355 的 SPI 是 8 位指令 + 8 位数据格式,读操作时,指令字节的最高位为 1,例如读地址 0x04 的XDATA3时,发送 0x84 然后读取一个字节。

3.2 用 STM32 HAL 库读取三个轴的原始值

我通常用 STM32 的 HAL 库来做演示,因为它可读性好。下面这段代码实现的是:初始化 SPI → 读取设备 ID → 配置量程和滤波 → 连续读取 X/Y/Z 轴原始值。

/* SPI 读取单字节 */ uint8_t ADXL355_ReadByte(uint8_t reg_addr) { uint8_t tx_data[2] = {0}; uint8_t rx_data[2] = {0}; tx_data[0] = 0x80 | (reg_addr & 0x3F); /* 读指令:最高位=1 */ tx_data[1] = 0x00; /* 占位字节 */ HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 2, 100); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); return rx_data[1]; } /* SPI 写单字节 */ void ADXL355_WriteByte(uint8_t reg_addr, uint8_t data) { uint8_t tx_data[2] = {0}; tx_data[0] = reg_addr & 0x3F; /* 写指令:最高位=0 */ tx_data[1] = data; HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, tx_data, 2, 100); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); } /* 读取设备 ID,用于验证通信 */ uint8_t dev_id = ADXL355_ReadByte(0x00); /* dev_id 应返回 0xED */

0x80 | (reg_addr & 0x3F)这个写法里,掩码 0x3F 是因为 ADXL355 的寄存器地址只有 6 位有效(最高两位是保留位或指令标志位)。读操作时先拉低 CS,发送指令字节和占位字节,同时在同一个事务里接收数据;写操作则直接发送指令和数据,中间不需要延时。

读取加速度数据时,每个轴的高 8 位、中 8 位、低 8 位分别存在相邻的 3 个寄存器里。以 X 轴为例,分别是XDATA3(0x08)、XDATA2(0x09)、XDATA1(0x0A)。完整拼装 20 位数据的代码段如下:

int32_t ADXL355_ReadAxis(uint8_t reg_h) { uint8_t h = ADXL355_ReadByte(reg_h); uint8_t m = ADXL355_ReadByte(reg_h + 1); uint8_t l = ADXL355_ReadByte(reg_h + 2); int32_t raw = ((int32_t)h << 12) | ((int32_t)m << 4) | (l >> 4); /* 20 位数据有符号扩展 */ if (raw & (1 << 19)) { raw -= (1 << 20); } return raw; }

注意l >> 4这一步:低字节只有高 4 位有效,这是 ADXL355 输出格式和常见 16 位传感器不一样的地方。如果你只取了高 16 位而丢掉低 4 位,等效分辨率会从 20 位降到 16 位,虽然噪声变化不大,但在静态倾角场景下的重复性会变差。

提示:读取设备 ID 返回 0xED 是通信成功的标志。如果读回来是 0xFF 或 0x00,先把 SPI 时钟降到 500 kHz,再检查 CS 极性是否设置正确,以及 VDDIO 是否有电压输出。

3.3 用 Python 在树莓派上读取数据,便于快速验证

如果手头没有 STM32 开发板,树莓派加spidev库也是快速验证的选择。下面的代码可以直接跑,前提是已经启用树莓派的 SPI 内核驱动。

import spidev import time spi = spidev.SpiDev() spi.open(0, 0) # 使用 SPI0 的 CE0 片选 spi.max_speed_hz = 1000000 spi.mode = 0b00 # Mode 0 def read_reg(reg): # 读指令: <1><5位地址><2位无关位>,实际发送时拼成1字节 tx = [0x80 | (reg & 0x3F), 0x00] rx = spi.xfer2(tx) return rx[1] def write_reg(reg, val): tx = [reg & 0x3F, val] spi.xfer2(tx) print("Device ID: 0x%02X" % read_reg(0x00)) write_reg(0x2D, 0x00) # POWER_CTL: 正常测量模式 write_reg(0x2C, 0x01) # RANGE: ±4g write_reg(0x2B, 0x0A) # FILTER: 500Hz 截止, 不启用高通 for _ in range(10): x = ((read_reg(0x08) << 12) | (read_reg(0x09) << 4) | (read_reg(0x0A) >> 4)) y = ((read_reg(0x0B) << 12) | (read_reg(0x0C) << 4) | (read_reg(0x0D) >> 4)) z = ((read_reg(0x0E) << 12) | (read_reg(0x0F) << 4) | (read_reg(0x10) >> 4)) # 有符号扩展 if x & (1 << 19): x -= (1 << 20) if y & (1 << 19): y -= (1 << 20) if z & (1 << 19): z -= (1 << 20) print("X=%6d Y=%6d Z=%6d" % (x, y, z)) time.sleep(0.1)

这段代码在write_reg(0x2D, 0x00)时将芯片从待机切到测量模式,RANGE设为 0x01(±4g),FILTER设为 0x0A(低通截止约 500 Hz)。注意spi.xfer2在树莓派上会同时收发相同字节数,所以读寄存器的第二个字节填 0x00 作为占位。

4. 深入寄存器配置:量程、滤波和内置自检的取舍

4.1 量程选择与灵敏度换算系数

ADXL355 的量程由RANGE寄存器(地址 0x2C)控制,其中range位(bit 1:0)决定满量程:

range量程灵敏度(LSB/g)典型应用
00±2g约 1092000 LSB/g高分辨率倾角
01±4g约 546000 LSB/g通用振动监测
10±8g约 273000 LSB/g冲击捕捉

灵敏度数字看起来很大,是因为输出是 20 位。换算成物理加速度的公式为:

加速度(g) = 原始值 / 灵敏度

例如在 ±4g 量程下读到的原始值是 546000,对应 1g。实际项目中,我建议把灵敏度作为常量写进代码,并在测试前用水平面校准一次。ADXL355 在水平放置且静态时,Z 轴读数应接近 1g,X 和 Y 接近 0mg。如果偏差超过 50mg,先检查 PCB 是否水平,再判断是否需要进行零点校准。

4.2 滤波配置的一个关键技巧

FILTER寄存器(地址 0x2B)控制低通和高通滤波器的截止频率。这地方有选择技巧:ADXL355 的内部低通滤波器是四阶的,在截止频率附近的相位延迟较大;如果你之后要做振动信号的相位分析,就要考虑这个延迟的影响。常见做法是直接配置到最高截止频率(约 500 Hz),然后在 MCU 或上位机里用 FIR 滤波器做二次处理——这样相位响应线性可控,不会因为芯片内部滤波器的非线性相位引入误差。

配置示例:

FILTER寄存器值低通截止频率(Hz)说明
0x0A约 500(每个轴)默认,最常用
0x09约 250减少高频噪声
0x08约 125低频结构监测
0x07约 62.5静态倾角测量

实际选型时有一个经验参考值:被监测信号的目标频率最高为 f,那么滤波器的截止频率设在 5f~10f 之间,留足余量避免幅值衰减。以风机塔筒一阶频率 0.3 Hz 为例,滤波截止设 4 Hz 就够了;而以齿轮箱监测为主时,要设到 500 Hz 才能捕捉到较高的啮合频率分量。

4.3 内置自检(Self-Test)的使用

资料包里通常会提到SELF_TEST寄存器(地址 0x28),但很少有人真正用它。这个自检会在各轴上施加一个已知的静电力偏移,模拟一个约 0.3g 的加速度。如果读到的轴数据在施加自检前后变化量在手册给定范围内,说明 MEMS 敏感结构和信号链基本正常。

执行自检的序列是:先读取三个轴的当前值作为基线,然后写SELF_TEST寄存器为 0x01,等待 10ms 后再读取三个轴。变化量应在 ±0.1g 以内才算合格。这里要注意:自检期间芯片必须处于测量模式,且不能有外部振动干扰,否则结果不可信。在产线测试里,这一步可以用来自动剔除焊接不良或 MEMS 受损的模组。

4.4 省电模式要考虑启动时间

如果项目需要电池供电,会在待机模式和测量模式之间切换来省电。但 ADXL355 从待机切到测量模式后,内部数字滤波器需要一段稳定时间,通常要等约 50ms 后数据才完全稳定。如果切到测量模式后立即开始读数据,前几十个点可能出现明显的直流漂移。常见的做法是:切换为测量模式之后先填充一个 50ms 延时的缓冲队列,或者直接丢弃前 10~20 个样本。

write_reg(0x2D, 0x00); // 进入测量模式 HAL_Delay(50); // 等待内部稳定 /* 丢弃前 20 个样本 */ for (int i = 0; i < 20; i++) { read_all_axis(); }

这段代码在每次唤醒后执行,能让后续采集的信号质量明显提升。在低功耗设计中,这种「启动丢弃窗口」是一个很实用的技巧。

5. 数据解析与常见坑:从原始值到真实物理量

5.1 亚 g 级振动数据的格式转换

拿到原始 20 位数据后,很多新手会直接除以 2^19 转换成小数,这种做法是错的。正确方式是用上一节提到的灵敏度 LSB/g 来除。以 ±4g 量程为例,原始值 273000 对应 0.5g。如果还想把单位转成 m/s²,再乘以 9.80665。

在嵌入式里为了效率,我一般不用浮点,而是用int64_t做定点运算:将加速度值放大 1000 倍存储,也就是用毫 g(mg)作为单位。例如:

int64_t accel_mg = raw_value * 1000 / 546000;

这样既避免了浮点运算的 CPU 开销,又保留了 0.001g 的分辨率。在数据上传时,直接把accel_mg转为字符串即可,上位机再除以 1000 显示。

5.2 网络反馈的数据分析和断点续传策略

在长时间在线监测项目中,ADXL355 的数据通常是定时通过无线网络上传的。常见做法是:MCU 按 1 kHz 采样率连续采集,每 1 秒形成一个 1k 点的数据块,用 zlib 或 LZ4 压缩后封装成帧,再交给 WiFi 或 LoRa 模块发送。如果传输失败,把数据块暂存在 SPI Flash 或 SD 卡中,等网络恢复后补传。这里有一个设计细节:ADXL355 的 FIFO 深度只有 96 个样本,远不够填满一帧,所以 MCU 必须实时搬移数据,不能依赖 FIFO 做长时间缓存。

如果要计算振动特征值,常用的是 RMS 和峰值。每收到 1 秒的数据,边采集边累积平方和,最后开平方得到 RMS 值:

for (int i = 0; i < 1024; i++) { sum_sq += (int32_t)accel_mg[i] * accel_mg[i]; } rms = sqrt(sum_sq / 1024); peak = max_value_in_buffer;

RMS 值常用于判断振动烈度等级(如 ISO 10816),峰值用于捕捉瞬时冲击。两者结合可以区分「持续振动超标」和「突发冲击」两类故障特征,是预测性维护里常用的双层判断逻辑。

5.3 多个容易忽略的坑

第一个坑是 SPI 读取速度太快导致寄存器数据错位。ADXL355 的 SPI 从机在连续读取相邻寄存器时没有 burst 模式——每次片选拉低后仅能读取一个地址的数据,要连续读三个轴的九个寄存器,必须将每个寄存器的读取作为独立的片选事务。如果像很多普通 SPI 传感器一样开启了「连续读」,读回来的数据会发生错位。在代码层面,一定要保证每次HAL_SPI_TransmitReceive前后都操作 CS 引脚。

第二个坑是中断引脚配置。ADXL355 的 INT1 引脚可以映射为数据就绪、FIFO 满、阈值比较等多种中断源。如果代码里初始化了中断而没正确配置中断映射寄存器,INT1 可能会一直保持高电平,导致 MCU 外部中断被反复触发。检查INT_MAP(地址 0x21)和INT_EN(地址 0x2D 之后的位)这两个寄存器,确保中断源映射到正确的引脚号。

第三个坑是温度漂移对静态测量的影响。ADXL355 的零 g 偏移温漂约为 ±0.2 mg/°C(典型值),在 25°C 的实验室标定后,到 60°C 的机柜环境里就会产生约 7 mg 的偏移,这在倾角测量里相当于 0.4° 的误差。如果项目要求高精度倾角,必须在系统里加装温度传感器做二次补偿,或者在使用前重新标定。常见做法是记录一组「温度-偏移」标定表,运行时插值修正。

6. 进阶:用低通滤波和 FFT 验证采集的数据质量,排查杂散信号

在完成基础读取之后,有一件事值得认真做——用一段已知频率的信号来验证整条采集链路是否干净。我的做法是用信号发生器加一个音圈电机或小型激振器,以 50 Hz 正弦信号激励传感器,然后采集一组 1024 点数据做 FFT,观察频谱中是否只有 50 Hz 主峰。

import numpy as np import matplotlib.pyplot as plt # raw_data 是从传感器读取的 mg 加速度序列,采样率 1000 Hz fs = 1000.0 # 采样率 N = 1024 # FFT 点数 win = np.hanning(N) data = raw_data * win # 加汉宁窗抑制频谱泄漏 freq = np.fft.rfftfreq(N, d=1/fs) amp = np.abs(np.fft.rfft(data)) * 2 / N plt.figure(figsize=(10, 4)) plt.plot(freq, amp) plt.xlabel('Frequency (Hz)') plt.ylabel('Amplitude (mg)') plt.xlim(0, 300) plt.show()

加汉宁窗是关键一步:不加窗时,50 Hz 信号的频谱会泄漏到附近频点,看起来像出现了 48 Hz 和 52 Hz 的杂散峰,容易被误判为故障特征。窗函数能有效抑制这种泄漏效应。如果 FFT 结果里除了 50 Hz 主峰外还有明显的 100 Hz 或多倍频峰,优先检查电源质量——开关电源的纹波会直接耦合进传感器输出,这时换成线性稳压器供电通常能改善 10 dB 以上的杂散抑制比。如果发现随机出现的宽带噪声抬升,先检查 SPI 线是否过长或与电源线平行布线,这是最常见的电磁干扰路径。

验证完链路后,把 FFT 分析脚本固化成一个常驻的检测工具,每次现场测试前先跑一遍,能大幅减少「数据采回来但不敢用」的问题。

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

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

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

立即咨询