sd-card - 与 ESP32、I2S MEMS 麦克风和 SD 卡同步缓冲区传输(FreeRTOS、PlatformIO、ESP-PROG)

标签 sd-card esp32 i2s

我知道这个论坛不喜欢这样的“开放式”问题,尽管如此,我还是希望有人能帮助我解开心中的结,非常感谢。

目标很简单:

  • 从 2 个 adafruit sph0645 麦克风读取立体声 32 位 44100 S/s I2S 信号
  • 创建 wav header 并将数据存储到 SD 卡上

我已经在这几天了,我知道这会比我最初想象的要复杂得多。主要原因:信号质量。与有关此主题的大多数教程一样,这些麦克风最简单的“hello world”是对 I2S 样本的循环轮询。轮询、填充缓冲区、通过串行输出或写入 SD 卡。这将返回 RL 音频的断断续续、嘈杂、加速版本。内部 DMA 缓冲区的填充可以看作是恒定的,但其余部分大多是困惑的,所以

如何将这些 DMA 缓冲区与代码的其余部分同步?

根据 STM32 HAL 的经验,我想象一些寄存器可以设置为在缓冲区已满时抛出中断,或者可以通过队列在任务之间发送事件。关于这个主题的示例要么在单声道主循环中进行轮询,采样率和位深度都非常糟糕,要么使用大量的过度杀伤代码,并且从不解决它的作用,“只需复制即可工作”,这都不好。 ESP32-Arduino 框架是否提供了一些正确的方法? espressif 文档并不值得期待,因为它们的一些 I2S 接口(interface)函数甚至无法工作(如果您也在研究这个主题,您也可能已经注意到 i2s_read 仅返回零)。只要提示正确的方向就会有所帮助,无论如何我正在编写自己的代码。中断?事件?计时器?轮询缓冲区已满?也许只有你自己知道。

祝你玩得开心,谢谢

最佳答案

感谢https://github.com/atomic14/我现在有了一个非常有效的同步方法的答案。此方法已被https://esp32.com/viewtopic.php?t=12546尝试过谁也没有完全理解发生了什么:espressif i2s 接口(interface)提供了一个存储在事件中的标志,每次一个指定的 dma 缓冲区收到完整的数据集时都会触发该标志,因此,已满。它看起来像这样:

while(<your condition>){

i2s_event_t evt;
if (xQueueReceive(<your queue>, &evt, portMAX_DELAY) == pdPASS){
  if (evt.type == I2S_EVENT_RX_DONE){
    size_t bytesRead = 0;
    do{

      //read data via i2s_read or i2s_read_bytes


    } while (bytesRead > 0);

此队列中不存储任何数据,而是存储一个标志,然后可以使用该标志来同步 dma 填充并进一步缓冲/计算/发送读取的数据。

但是这仅在您在特定设置中安装 i2s 驱动程序时才有效。而不是使用

i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);

在您的设置中,您可以通过传递队列句柄和长度来激活事件的“关联性”:

i2s_driver_install(I2S_NUM_0, &i2s_config, 4, &<your queue>);

希望这有助于入门,它确实对我有帮助。

关于sd-card - 与 ESP32、I2S MEMS 麦克风和 SD 卡同步缓冲区传输(FreeRTOS、PlatformIO、ESP-PROG),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66043272/

相关文章:

android - 查找SD卡上的所有文件

c++ - CMake 静态库链接(预编译.a)

c - tm 结构转换为错误的 time_t

microcontroller - SPI 事务提前终止 - ESP-IDF

安卓保存到SD卡

android - 从 Android Market 安装到 SDCARD

audio - PIC32MX : SPI1CON. SPIBUSY 位永远不会被清除

在 C 中将立体声 wav 转换为单声道

android - 查找可移动 SD 卡的位置