☰
LIS25BA高带宽TDM接口加速度计在振动检测中的应用与STM32驱动实践
2026/11/2 18:12:35 网站建设 项目流程

最近在做一个工业振动监测的小项目,芯片选了 LIS25BA。看名字可能第一反应是“这不就是个三轴加速度计吗”,但它跟常见的 ADXL345、MPU6050 完全不是一个路数:低噪声、高带宽、TDM 接口,专门为振动/声音采集设计。折腾了两周,把 TDM 时序和驱动代码都理清了,也顺手把管道泄漏检测的算法思路跑了初步验证,这里记录一下整个方案的设计取舍和实际操作中踩过的坑。

后台经常有人问:LIS25BA 到底是什么定位?TDM 接口和普通 SPI/I2C 加速度计比有啥优势?主设备读取数据和从设备准备好数据是否都在 BCLK 上升沿?这篇文章专门回答这些问题,适合正在选型加速度计、准备接触 TDM/I2S 总线,或想用 MEMS 做振动检测的工程师。

1. LIS25BA 定位与核心特性

1.1 关键参数拆解

先说结论:这是一颗“音频级”加速度计。普通加速度计用来测姿态、计步、碰撞,采样率最多一两千赫兹就够用;LIS25BA 则把性能目标放在了捕捉声波和结构振动上,所以它的参数表跟普通传感器放在一起对比,差距非常明显。

我在选型时重点关注了三项指标:

参数LIS25BA典型普通加速度计为什么我在意
噪声密度低于 1 μg/√Hz 级别100~300 μg/√Hz微弱的泄漏振动信号才不会被噪声淹没
带宽最高接近 5kHz400Hz~1kHz管道泄漏和水锤信号的高频成分往往超过 2kHz
输出接口TDM 数字音频格式SPI/I2C可以直接挂在音频总线上,多设备同步采集
分辨率24 位16~18 位动态范围大,弱信号和强冲击能同时观察

噪声密度这个参数我单独展开一下。MEMS 加速度计的噪声密度可以理解成“每单位频率带宽内掺入了多少无效信号”。LIS25BA 能做到低于 1 μg/√Hz,意味着在 1kHz 带宽内等效噪声只有几十微 g 级别,普通加速度计则是几百到上千微 g。在管道泄漏这种场景下,塑料管壁上的泄漏振动加速度往往只有几 mg 到几十 mg,普通传感器很容易被自身噪声淹没,而它勉强能看清信号轮廓。这也是我最终选择这颗芯片的直接原因。

1.2 为什么 TDM 接口在振动/音频场景中很有价值

传统传感器用 SPI/I2C 输出,主控需要主动发起读操作,数据是“请求后回来”的模式。TDM 接口则完全不同:它本质上是一种时分复用的同步串行总线,传感器每个采样周期都主动把数据放在数据线上,主控只需要持续接收即可。

这种差异在实际项目里非常关键。举个例子,在骨传导耳机或者振动降噪场景中,加速度计和麦克风往往需要同时采集数据,并且逐样本对齐。如果用 I2C 去分别读取,总线请求延迟、中断响应时间都会造成不确定的样本错位。而 LIS25BA 挂在同一条 TDM 总线上时,只要配置好时隙,主控读完一整帧数据,麦克风和加速度计的样本就已经天然对齐了,不需要额外的软件同步逻辑。

此外,TDM 接口配合 DMA 搬运可以实现几乎零 CPU 开销的数据流。我在 STM32 上直接把 SAI 外设收到的 TDM 帧通过 DMA 送进环形缓冲区,CPU 只在缓冲区满时做一次算法处理,中间完全不进中断,这在需要同时运行运动控制算法的系统里非常香。

2. TDM 接口原理与 BCLK 时序细节

2.1 TDM 协议基础

TDM 总线看起来有点像 I2S,但比 I2S 更灵活。它至少有三根线:位时钟 BCLK、帧同步信号 FS、数据线 DAT。有些方案还会加一根 MCLK 主时钟,用来保证高精度采样率,但 LIS25BA 实际使用中可以直接用 BCLK 做系统时钟,不需要单独 MCLK。

帧同步信号定义一帧的开始,通常每个采样周期拉高一次。每位数据在 BCLK 驱动下依次移入/移出数据线,一个“帧”内可以拆成多个 slot(时隙),每个 slot 可以是 16/24/32 位。麦克风占一个 slot,LIS25BA 占三个 slot(分别对应 X、Y、Z),这样一条总线上就能同时挂多个设备。

LIS25BA 的 TDM 接口支持配置 slot 的起始位置和数量,通常我会把它配置成 4 个 slot、每个 slot 32 位,其中前三个 slot 放 X/Y/Z 数据,第四个 slot 可以用于其他从设备或者直接补零。这样配置的好处是总线上所有 32 位 slot 对齐,DMA 缓冲区处理逻辑会简单不少。

2.2 主设备读取数据和从设备准备数据,都是在 BCLK 上升沿吗

这个问题我调试时纠结了很久,也看了不少论坛,最后通过逻辑分析仪才算彻底确认。答案不是简单的“都在上升沿”,而是取决于具体接口标准以及主从设备的实现方式。

在绝大多数 I2S/TDM 系统中,主设备(比如 MCU 的 SAI 模块)是在 BCLK 的上升沿采样数据线,从设备(比如 LIS25BA)在 BCLK 的下降沿更新数据线。也就是说:

  • BCLK 下降沿:从设备把下一位数据放到 DAT 线上;
  • BCLK 上升沿:主设备读取 DAT 线,此时数据已经在下降沿之后稳定下来。

这种设计非常合理,因为数据变化和采样发生在不同边沿,避免了主设备在数据翻转瞬间采样导致的亚稳态问题。你可以把它理解成“踢球”:从设备在下降沿把球踢出来,主设备在上升沿等球落到脚边再接住,中间留有半个周期的时间余量。

但要注意,这只是最常见的模式。I2S 标准里也存在左对齐、右对齐等变体,有些主设备甚至允许配置成下降沿采样,因此最稳妥的做法不是凭空猜,而是去查 LIS25BA 数据手册里的 AC 时序图。手册中通常会明确给出数据在 BCLK 哪个边沿翻转、哪个边沿建议采样。当时我手里的手册标注的是“data toggled on falling edge, sampled on rising edge”,所以最终确定按上升沿采样来配置。

如果你也在调这类问题,建议把逻辑分析仪直接并到 BCLK 和 DAT 上观测。只要看到了实际的波形,边沿关系一目了然,很多论坛上的争执其实都是因为大家在不同主设备上调试,行为不完全一致。

2.3 LIS25BA 数据手册的时序参数与配置

除了边沿关系,还要关注 BCLK 的最大频率。LIS25BA 的典型 ODR(输出数据率)是 48kHz,也就是说每个样本周期约 20.8 微秒。如果一帧包含 4 个 slot,每个 slot 32 位,那一帧就是 128 bit,BCLK 频率至少是 48kHz × 128 = 6.144MHz。这个频率对 STM32 的 SAI 外设来说完全没问题,但普通 I2C 根本做不到这个吞吐量。

实际操作中我在 STM32F407 上把 SAI 的 BCLK 配到 6.144MHz,Frame length 设置为 128 bit,Frame sync 设置为 64 个 BCLK 周期,也就是半帧高电平半帧低电平。这样一帧数据正好在 20.8 微秒内传完,时间窗口卡得很准。

还有一个容易忽略的参数是 slot 的位长。LIS25BA 输出 24 位有效数据,但接口上默认建议按 32 位传输,多出来的高 8 位或低 8 位补零取决于寄存器配置。我习惯把左对齐(MSB first)打开,数据放在 32 位容器的最高 24 位,这样后面解析数据时符号扩展最方便。

3. 从零开始:STM32 读取 LIS25BA 的完整过程

3.1 硬件连接

我用的是 STM32F407 开发板,板载 SAII 接口,引脚设计如下:

LIS25BA 引脚STM32 引脚说明
VDD3.3V数字电源
VDD_IO3.3VIO 电源,可以单独接不同电压
GNDGND地线尽量短粗
BCLKPB10 (SAI1_SCK_A)主设备提供位时钟
FSPB9 (SAI1_FS_A)帧同步信号
DATPC3 (SAI1_SD_A)数据线,LIS25BA 输出接 MCU 输入

电源部分我踩过一个坑:LIS25BA 对电源噪声比较敏感,如果直接用开发板的 3.3V 开关电源,采集到的波形底噪明显偏大。后来在 VDD 引脚旁边加了 1μF 和 0.1μF 并联电容,并且尽量靠近引脚放置,底噪才降下来。如果是做产品设计,建议用 LDO 单独给传感器供电,不要和电机驱动等大电流负载共电源。

3.2 寄存器配置与初始化流程

这颗芯片的寄存器并不多,核心配置集中在几个控制寄存器里。我先说初始化流程,再给出寄存器说明。

  1. 复位芯片:往 SOFT_RESET 位写 1,延时至少 10ms;
  2. 配置 ODR 和带宽:设置输出数据率为 48kHz;
  3. 配置 TDM 接口:选择 slot 数量、slot 长度、FS 极性;
  4. 打开 X/Y/Z 输出通道,设为 TDM 模式;
  5. 使能传感器,等待 STATUS 寄存器中的 DRDY 置位。

这里有个细节:LIS25BA 的 TDM 模式不是默认开启的,必须显式配置接口寄存器,否则 DAT 线上不会输出数据。我看到很多人在论坛问“为什么读不到数据”,多半是这一步漏了。

3.3 SAI+DMA 读取的代码实现

我用的 STM32 标准外设库,但核心代码用 HAL 看起来会更直观。下面是初始化 SAI 并配置 DMA 接收的关键片段。

// 使能 SAI 时钟和 DMA 时钟 __HAL_RCC_SAI1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); // DMA 接收配置:从 SAI1_A 数据寄存器搬到内存缓冲区 static void DMA_Config(void) { hdma_sai1_rx.Instance = DMA2_Stream1; hdma_sai1_rx.Init.Channel = DMA_CHANNEL_0; hdma_sai1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_sai1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_sai1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_sai1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_sai1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_sai1_rx.Init.Mode = DMA_CIRCULAR; hdma_sai1_rx.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_sai1_rx); __HAL_LINKDMA(&hsai_BlockA, hdmarx, hdma_sai1_rx); } // SAI 主接收模式,TDM 4 slot,每个 slot 32bit static void SAI_Config(void) { hsai_BlockA.Instance = SAI1_Block_A; hsai_BlockA.Init.AudioMode = SAI_MODEMASTER_RX; hsai_BlockA.Init.Synchro = SAI_ASYNCHRONOUS; hsai_BlockA.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; hsai_BlockA.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; hsai_BlockA.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_QF; hsai_BlockA.Init.AudioFrequency = 48000; hsai_BlockA.Init.SynchroExt = SAI_SYNCEXT_DISABLE; hsai_BlockA.Init.MonoStereoMode = SAI_STEREOMODE; hsai_BlockA.Init.CompandingMode = SAI_NOCOMPANDING; hsai_BlockA.Init.TriState = SAI_TRISTATECONFIGURATION_DISABLE; HAL_SAI_Init(&hsai_BlockA); SAI_FrameConfig frame; frame.FrameLength = 128; // 4 slot × 32bit frame.ActiveFrameLength = 64; // FS 高电平半个 frame frame.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; frame.FSPolarity = SAI_FS_ACTIVE_HIGH; frame.FSOffset = SAI_FS_FIRSTBIT; frame.FirstBit = SAI_FIRSTBIT_MSB; frame.SlotSize = SAI_SLOTSIZE_32BIT; frame.SlotNumber = 4; frame.ActiveSlot = SAI_SLOT_ALL; HAL_SAI_ConfigFrame(&hsai_BlockA, &frame); }

DMA 配置成循环模式后,只要 SAI 开始接收,数据就会自动写入 DMA 缓冲区。缓冲区大小建议设成帧数的整数倍,比如 128 帧,这样每满一次缓冲区正好对应固定时长,方便做定时处理。

3.4 24 位数据转换与滤波

LIS25BA 每个轴输出 24 位补码,但我配置的 slot 是 32 位,因此 DMA 缓冲区里每个轴的数据是 32 位内存对齐的。解析时直接取最低 24 位,再做符号扩展。

int32_t raw_x = (buffer[0] << 8) >> 8; // 保留符号 int32_t raw_y = (buffer[1] << 8) >> 8; int32_t raw_z = (buffer[2] << 8) >> 8;

这里左移 8 位再右移 8 位,是为了把 24 位补码扩展成标准 32 位 signed int。如果你配置的是右对齐,则需要先右移再扩展,逻辑完全不同,别照抄。

接下来把原始码转成物理量。LIS25BA 的典型满量程是 ±3.85g,24 位分辨率下对应比例因子约为:

满量程 7.7g,2^23 = 8388608,所以比例因子约 0.917μg/LSB。实际使用中我会在系统上电后静止放置 1 秒,计算参考零点,再做差分,这样可以消除零偏。

滤波方面,我习惯先用一阶高通滤掉直流分量,再根据目标频带做带通滤波。比如水管泄漏检测关注 1kHz~3kHz 频段,我会用 IIR 带通滤波器,在 STM32F407 上做 3 轴滤波,CPU 占用率依然很低。后续如果需要更高性能,可以上 STM32H7,配合硬件浮点单元和双 DMA 做更复杂的算法。

4. 实操应用:管道泄漏振动检测与更多

4.1 基于三轴加速度计的泄漏振动检测思路

这个话题在工业圈热度不低。塑料水管发生泄漏时,流体从破损处喷射会产生湍流,激发管壁高频振动。这种振动会沿着管壁传播几十米,利用高带宽、低噪声加速度计贴在管壁表面,就能“听”到泄漏。

刚才说 LIS25BA 的带宽接近 5kHz,恰好覆盖泄漏信号的主要频段。测试中我把传感器用双面胶贴在 PVC 管外壁,用稳压阀制造微小泄漏,采集到的时域波形几乎看不出异常,但频谱在 1.5kHz~2kHz 附近有明显能量抬升。这个频段相对干净,环境噪声和电机运转噪声主要分布在 500Hz 以下,所以通过带通滤波加能量积分就能很好区分。

4.2 信号处理与判断流程

完整的判断流程我分成五步:

  1. 连续采集 8192 点数据,采样率 48kHz,约 170ms;
  2. 对每个轴做去直流处理;
  3. 级联带通滤波器,中心频率设在 1.6kHz,Q 值约 3;
  4. 计算三轴滤波后信号的能量:E = sqrt(Ex² + Ey² + Ez²);
  5. 与预设阈值比较,超过阈值且持续 100ms 以上判定为疑似泄漏。

阈值怎么定?我建议在实际安装环境中先采集一段背景噪声,计算能量均值和标准差,阈值设为均值 + 5 倍标准差。这样可以规避环境噪声的随机波动。测试下来,在正常供水管道附近,阈值设置在 5~20mg 左右,就能稳定捕捉到阀门微开时的泄漏信号。

4.3 在运动控制系统中加入振动监测

顺便说一个我最近在研究的扩展玩法:把 LIS25BA 接入运动控制系统。很多做 STM32H7 运动控制的工程师都在追求高脉冲输出频率,比如用双 DMA 实现 8 轴插补,单轴脉冲频率跑到 500kHz,3 轴甚至到 1MHz。但高速运动下机械结构容易出现共振,如果没有振动传感器,很容易在运行一段时间后出现丢步或异响。

把 LIS25BA 贴到运动平台底座上,通过 TDM 总线高速采集振动数据,一旦检测到共振频段的能量异常上升,控制算法可以自动调整加减速曲线或降速运行。这种方案的好处是传感器和运动控制主控共用同一条总线,数据延迟低,而且不需要额外占用 SPI/I2C 接口,非常适合算力紧张的多轴控制场景。

当然,这只是一个试验性思路,机械结构和安装位置对共振检测效果影响很大,后续我打算把算法整合进运动控制源码里,做一套完整的振动抑制模块后再单独写一篇文章。

5. 常见坑位与排查实录

5.1 数据错位、丢帧问题

调试中最常见的问题是数据错位,也就是读到的 X/Y/Z 值互相串了。这通常不是芯片坏了,而是 TDM slot 配置和实际总线上设备占用的 slot 不对应。

我遇到过一种情况:总线上先挂了麦克风,占用 slot 0,LIS25BA 配置成从 slot 1 开始输出。如果 MCU 的 DMA 缓冲区按照从 slot 0 开始解析,就会把麦克风数据当成第一个轴数据,三个轴全部错位。解决办法是仔细检查寄存器里的 slot 起始位置配置,并在代码里打印第一个字来判断它到底对应哪一路设备。

还有一种丢帧现象,表现为数据偶尔跳变或出现大毛刺。排查后发现是 SAI 的 FIFO 阈值和 DMA 优先级不够,导致 FIFO 溢出。把 DMA 优先级调到最高,并把 SAI 的 FIFO 阈值改成半满中断,问题就消失了。

5.2 噪声与电源问题

如果数据噪声明显偏大,首先怀疑电源,其次是地线回路。LIS25BA 是低噪声传感器,对电源纹波非常敏感。我在面包板上测试时噪声是正常的 3 倍,后来改成在 PCB 上集中供电,并且模拟地和数字地在传感器附近单点连接,噪声才降下来。

如果你是做原型验证,至少要做到两点:电源线尽可能短;传感器下方铺完整地平面,不要走开关电源的电流回路。另外,不要在 DAT 数据线上串太大的电阻,否则会改变信号边沿速率,导致主设备采样不稳定。

5.3 逻辑分析仪验证要点

调 TDM 接口,逻辑分析仪是必需品。我一般会观察以下几点:

观察项正常情况异常情况
BCLK 频率6.144MHz 左右稳定波动过大说明时钟配置有问题
FS 脉冲周期48kHz,周期 20.8μs周期不对说明分频算错
DAT 数据变化每帧前三个 slot 均有跳变全部不变说明芯片没进入 TDM 输出模式
数据边沿数据变化发生在下降沿若在上升沿变化,MCU 采样点要重新确认

逻辑分析仪采样率建议设置在 50MHz 以上,至少是 BCLK 的 8 倍,否则测不出边沿细节。采集时用 BCLK 作为触发源,抓一帧完整波形,然后把数据解析成十六进制,确认前三个 slot 的数据是否随板子倾斜而变化。这个验证方法百试百灵。

6. 我的几点工程心得

第一次接触 LIS25BA 的时候,我以为 TDM 接口是难题,后来发现真正花时间的反而是电源和地线设计。低噪声传感器对硬件细节的要求确实比普通数字传感器高一个档次,但也正因为如此,它能做到的信号质量是普通 I2C 加速度计没法比的。

在数据解析上,我强烈建议从一开始就引入环形缓冲区和双 DMA 结构,不要用中断逐字节读取。TDM 是高吞吐量接口,1 秒 48k 帧、每帧 16 字节,数据量接近 768kByte/s,中断方式不仅占用 CPU,还容易丢数据。DMA 循环模式配合半满和全满中断,既稳定又省电。

如果后续要把 LIS25BA 用在电池供电的无线传感器节点上,可以关注它的睡眠模式和唤醒功能,虽然这次没细写,但低功耗场景下的配置逻辑和普通加速度计差别不大。总的来说,这颗芯片在振动检测、音频感知和工业状态监测领域都有很大潜力,先把它跑通,后面做算法就有可靠的硬件基础了。

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

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

立即咨询