代码之家  ›  专栏  ›  技术社区  ›  richbai90

在STM微控制器上使用DFSDM录制音频

  •  2
  • richbai90  · 技术社区  · 3 年前

    在用于物联网节点的STM32L4发现套件上( B-L47E-IOT0A1 ),有两个 MP34DT01 麦克风:一个 其中LR被拉至VDD,而第二个LR被拉低。 DFSDM1_CKOUT DFSDM1_DATIN2 两者都连接。我有这个板,系统时钟设置为80MHz DFSDM CH2 在中启用 DMA 模式此外,我将过滤器设置为连续模式 Fosr 设置为52,以及 Iosr 在8。我可以得到值,这样我就知道麦克风在工作,但试图播放音频会导致一堆静态。我认为我的采样率应该是48KHz,因为内部SPI时钟分频器设置为4-- (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
          }
    }
    
    

    我可以使用以下shell命令检索数据并将其保存到二进制文件中:

    screen -S audio -L -Logfile audio.bin /dev/ttyACM1 9600, cs8

    我使用以下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)
    

    当我播放音频文件时,它都是静态的。在这个过程中,我哪里出了问题?

    1 回复  |  直到 3 年前
        1
  •  0
  •   Craig Estey    3 年前

    注意事项: 不是一个完整的解决方案,但有些事情需要尝试。。。

    尽管如此,这可能是布线或DMA设置等方面的问题。有一些事情需要首先检查,以确保您的捕获和传输过程是正确的。

    1. 根据我的最高评价: 您正在输出单声道16位,即2个字节,但您指定了4个?此外,比特率通常为44100(pc音频)或48000(mp4音频),所以48077对我来说似乎很奇怪。

    2. 你能 验证 您的电脑是否正确捕获了数据?也就是说,波特率等是正确的。电脑和STM32是否设置正确?

    3. 让STM32在开始时输出一个固定的已知字节串。(例如) for (i = 0; i < 256; ++i) buf[i] = i; 修复[和 可验证的 ]模式应该启动 .bin 文件您可以使用十六进制编辑器对此进行检查。

    4. 如果您将电脑设置为[通过扬声器]输出纯音(如正弦波)并录制,当您获得 箱子 在你电脑上的备份文件中,你应该能够绘制原始数据并看到正弦波。

    5. 你能保证DMA完成后,它会完全填满缓冲区吗?有没有可以调用的函数来获取字节数 事实上 由DMA传输?(例如)你能完成一个 更少 字节?

    6. 你能在DMA和你的代码之间有一个竞争条件吗?你的缓冲方案是否足够好,可以防止DMA向上半部分和下半部分输出,但速度太快,以至于它试图再次[部分]填充第一个缓冲区?

    7. 换句话说,您的基站等待“DMA完成”标志(例如。 audioFilterHalfCplt )并获取数据。但是,是什么阻止DMA写入 下一个 一大块数据进入缓冲区 虽然 你在循环中把它拔出来?

    推荐文章