3

我正在使用带有 microSD 卡的 STM32F4 微控制器。我正在通过 DMA 捕获模拟数据。

我正在使用双缓冲区,一次采集 1280 个(10*128 - 10 个 FFT)样本。当一个缓冲区已满时,我设置一个标志,然后一次查看 128 个样本并对其运行 FFT 计算。所有这一切都运行良好。

数据正在以我想要的速率进行采样,FFT 计算正如我所期望的那样。如果我只是让程序运行一秒钟,我会看到它运行 FFT 大约 343 次(44000/128)。

但问题是我想将此 FFT 中的 64 个值保存到 SD 卡。

  • 我正在使用 HCC fat 文件系统库。
  • FFT 计算的每个循环我都将 64 个值复制到一个数组中。
  • 每 10 次计算后,我将这个数组的内容写入文件并重新开始。
  • 该数组存储 640 个 float_32 值 (10*64)。

这对于一秒钟的测试运行非常有效。我将 22,000 个值存储到 SD 卡中。

但是随着时间的增加,我开始丢失样本,因为 SD 卡需要更长的时间来写入。我需要 SD 卡始终存储超过 87 kbit/s(4 字节 * 64 * 343 = 87808)。我尝试增加 DMA 缓冲区样本大小,然后增加它的写入次数,但没有发现它有帮助。

我使用的是 4 类 8G microSD 卡。我将 SD 卡格式化为默认的 FAT32 分配单元大小 2048。

我应该如何组织数据缓冲以实现这一点?我认为使用更少的写入可能会有所帮助。排队有用吗?我将如何实现这一点,有人有例子吗?

我看到 Clifford 也有类似的问题,他正在使用队列, 如何使用 SD 卡以 48 ksamples/s 的速度记录 16 位数据?.

4

3 回答 3

0

就我而言,我通过尝试大量不同的卡来让它工作——它们变化很大。如果我有足够的 RAM 可用于更长的缓冲区,那也可以。

如果您不使用 RTOS,则队列缓冲选项可能对您不可用,或者至少实现起来并不简单。

使用 RTOS 队列,我建议您创建一个长度为每个长度的消息队列,队列中的消息64*sizeof(float_32)数量将取决于您需要处理的卡延迟量;例如,长度为 343,将维持 1 秒的卡停顿,并且需要 87Kb 的 RAM。然后应用程序将有一个高优先级线程执行 FFT 并将数据放入队列中,而低优先级线程从队列中获取数据并写入文件。

您可以通过在开始写入之前在 DMA 缓冲区中累积多个消息块来进一步提高性能,并且仔细选择最佳 DMA 缓冲区长度可能会有一些好处。

于 2014-02-04T21:08:44.997 回答
0

Flash 对覆盖非常非常敏感。写入 3kB,然后再写入 3kB 可能算作覆盖前 4kB。就您而言,无论如何您都没有充分的理由想要如此小的写入。我建议 16 kB 写入(32 帧/写入 * 64 样本/帧 * 4 字节/样本)。您每秒需要 5 或 6 次写入,这应该符合任何旧 SD 卡的规格。

现在你很有可能在写作时又得到了 1280 个样本;你必须在另一个线程上处理这个问题。应该没问题,因为写入应该在不使用 CPU 的情况下阻塞(这是一个低级 Flash 延迟)

于 2014-02-04T21:19:08.177 回答
0

问题的最可能原因可能是您通过库连接卡的方式。

通过 SPI 协议(我假设在这里使用)的 SD 卡可以以 512 字节扇区为单位读取或写入,一些 SD 命令可以流式传输(以更快地执行顺序扇区访问)。SD卡SPI协议的一个重要元素是各种延迟,您必须轮询卡是否可以开始操作(例如将数据写入扇区)。

您应该阅读该库的 API 以了解其编写过程是如何工作的。您将需要执行一些常规操作,最终将轮询卡以了解写入过程是否可以继续。有些卡在准备好操作之前可能需要一定数量的访问,有些卡可能会使用超时来进行状态转换。让函数调用相对较少(例如每 2-3 毫秒一次)来预期卡同时准备好可能效果不佳。你必须继续唠叨它是否已经完成。

仅根据自己在 SD 接口方面的经验。

于 2017-05-19T12:36:53.673 回答