You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32L4开发板DFSDM录音回放有杂音问题求助

问题

在STM32L4 IoT节点开发板(B-L47E-IOT0A1)上搭载两颗MP34DT01麦克风:一颗LR引脚接VDD,另一颗LR引脚拉低,均连接DFSDM1_CKOUT与DFSDM1_DATIN2。系统时钟设为80MHz,启用DFSDM CH2的DMA模式,滤波器设为连续模式,Fosr=52、Iosr=8。能获取数据但回放音频全是杂音,计算采样率应为48KHz——(80MHz/4)/(52 * 8) = 48KHz。

相关代码如下:

Audio.c

#define AUDIO_LEN 240
#define H_AUDIO_LEN 120

int32_t micRecBuf[AUDIO_LEN];
int32_t micAudioBuf[AUDIO_LEN];
volatile uint8_t audioFilterHalfCplt = 0;
volatile uint8_t audioFilterCplt = 0;

void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
    audioFilterHalfCplt = 1;
}
void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
     audioFilterCplt = 1;
 }

void micInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
    HAL_DFSDM_FilterRegularStart_DMA(hdfsdm_filter, micRecBuf, AUDIO_LEN);
}

主循环代码

while(true) {
   // first half of DMA is filled, now process
    if (audioFilterHalfCplt == 1) {
      // fill the audio buffer
      for (i = 0; i < H_AUDIO_LEN; i++) {
        micAudioBuf[i] = micRecBuf[i] << 8; // remove meta data
      }
      // reset the flag
      audioFilterHalfCplt = 0;
    }
    // second half is filled, finish process
    if (audioFilterCplt == 1) {
      // fill the audio buffer
      for (i = H_AUDIO_LEN; i < AUDIO_LEN; i++) {
        micAudioBuf[i] = micRecBuf[i] << 8; // remove meta data
      }
}

数据导出流程:

  1. 用shell命令保存二进制文件:
screen -S audio -L -Logfile audio.bin /dev/ttyACM1 9600, cs8
  1. Python脚本转存为WAV:
#!/usr/bin/env python3

import wave

with open("audio.bin", "rb") as input_file:
    data = input_file.read()
    with wave.open("output.wav", "wb") as output_file:
        output_file.setnchannels(1)  # Assuming mono
        output_file.setsampwidth(4)  # Assuming 16-bit samples (2 bytes)
        output_file.setframerate(48077)  # Set the sample rate
        output_file.writeframesraw(data)

回放WAV文件全是杂音,请问流程中哪里出错了?


分析与解决

1. Screen日志非纯二进制数据

screen -L默认会在日志中插入时间戳、状态信息等额外内容,不是纯原始音频数据,这会直接导致audio.bin包含大量无效数据,回放必然是杂音。

修正:
改用纯二进制捕获工具,比如先配置串口参数:

stty -F /dev/ttyACM1 115200 cs8 -cstopb -parenb

再直接捕获原始数据:

cat /dev/ttyACM1 > audio.bin

2. 串口波特率严重不足

48K采样率下,每个32位采样占4字节,每秒需传输48000*4=192000字节,但9600波特率(cs8配置)的实际传输速度仅约960字节/秒,远低于需求,会导致数据大量丢失、错位。

修正:

  • 将STM32串口波特率至少提升至230400,建议用115200或460800
  • 确保screen或捕获命令的波特率与STM32配置完全一致

3. WAV参数配置矛盾

Python脚本中setsampwidth(4)表示32位采样,但注释标注“16-bit samples (2 bytes)”,参数与实际意图不符;若实际需要16位音频,直接写入32位数据会导致格式错误。

修正:

  • 若保留32位采样:将注释改为// 32-bit samples (4 bytes),保持setsampwidth(4)
  • 若转16位采样:将数据缩放到16位范围(比如micAudioBuf[i] >> 16,确保数据在-32768~32767区间),然后设置setsampwidth(2)

4. DFSDM数据处理错误

两颗麦克风共用DATIN2,通过LR引脚实现时分复用双声道,但当前代码按单声道处理,会把左右声道数据混叠;同时micRecBuf[i] << 8的操作盲目,DFSDM的32位输出中有效音频数据的位置需根据配置确定,盲目移位可能丢失有效数据或保留无效位。

修正:

  • 区分双声道数据:每两个采样对应左、右声道,单独提取目标声道的数据
  • 确认DFSDM输出格式:查看CubeMX配置或STM32手册,找到有效数据的位数与偏移,比如若有效数据是24位,可能需要右移8位而非左移

5. DMA回调标志未完全重置

主循环中处理audioFilterCplt时未重置标志位,会导致该分支被反复执行,重复处理同一数据块,造成数据错乱。

修正:
在audioFilterCplt分支末尾添加标志重置:

if (audioFilterCplt == 1) {
  // fill the audio buffer
  for (i = H_AUDIO_LEN; i < AUDIO_LEN; i++) {
    micAudioBuf[i] = micRecBuf[i] << 8; // remove meta data
  }
  audioFilterCplt = 0; // 新增:重置完成标志
}

内容的提问来源于stack exchange,提问作者richbai90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:15:18