1

我正在使用 STM32F103C8,并且 FATFS R0.11 可以正常工作(这是 CUBEMX 默认在 STM32F103C8Tx 上使用的最新版本),但读取速度非常低,大约为 100 kB/s。

SPI 时钟设置为 18 MHz(从 9 MHz 更改,但没有区别,与 4.5 MHz 相反,它对读取速度的影响很明显 - 读取时间增加了 30%)并且我已经关闭了大部分额外的节省 RAM 的选项。打开两个文件后,我剩下大约 10 kB(从 20 kB)的 RAM(在 KEIL 中编译时,STM32CUBEIDE 使用了更多的 RAM),这对于我的项目的其余部分来说应该足够了。

该文件被读入 4096 字节的缓冲区,一次 2048 字节(它将是一个 wav 文件,将以等于 22050 Hz 的采样率发送到 I2C DAC,所述缓冲区的大小取决于关于我项目其他重要部分的 RAM 使用情况,可能最终会增加,但目前尚不清楚)。

单次 2048 字节读取操作大约需要 20 ms。我使用的是 4 类和 10 类 SD 卡,但结果是一样的。所述 SD 卡的集群大小,当减少到 512 字节时,使我能够实现上述 20-21 毫秒的每次读取,而不是在不同格式设置下的 25 毫秒。由于我还计划显示图像,因此将不胜感激任何较低的读取速度。时间是在 HAL_GetTick() 函数的帮助下测量的。

我尝试一次读取 4096 个字节,甚至 8192 个字节,但是这样做所花费的时间适当地缩放,因此在这些测试期间没有记录任何好处。我什至尝试使用完整格式而不是默认的快速选项,但没有任何改变。

您是否认为,我可以做些什么来进一步减少阅读时间,或者这是否以某种方式、形状或形式受我的设置限制,或者我做错了什么?下面,我把存档和我的项目联系起来,大家可以自己编译测试(我在Keil uVision5下编译,0个错误,0个警告)

出于好奇,我还在读取文件期间探测了 SPI 接口(这是我唯一在做的事情,目前没有写入 SD 卡)。

链接到 .rar 存档

从上到下:SCK-黄色、MISO-洋红色、MOSI-青色、CS-蓝色。我添加了额外的延迟来显示传输的不同部分:第一个块负责挂载和打开第一个文件,在 4 毫秒延迟后我打开第二个文件(延迟打开第一个文件不会导致任何延迟),然后在 2 毫秒后我执行第一次读取,在额外的 2 毫秒延迟后,我读取了接下来的 2048 个字节。 完整的通信,增加了延迟

放大片段

我的 SD 卡适配器和连接:标准的 micro SD 到 SD 适配器,带有焊接的金针和电线,连接无焊面包板上的所有东西,ST-LINK V2.1 从 STM32F429ZI-DISC1 “借来”。PA4-CS、PA5-SCK、PA6-味噌、PA7-MOSI。谢谢阅读 :)

4

1 回答 1

1

好的,我设法弄清楚了,您可以在上面的附图中清楚地看到,SPI 总线上连续动作之间的延迟很长,这似乎是 HAL 做了很多开销工作的原因,这会减慢速度下。我用自定义函数替换了发送和接收数据的默认函数,它在寄存器上做所有事情,读取时间减少了四倍,现在我可以在 5-6 ms 内读取 2 kB 的数据,即等于大约 400 kB/s。它仍然很低,所以我会等待一段时间,看看是否有人对如何进一步改进有更好的想法。我还将 FATFS 升级到版本 R0.12c,但这并没有改变任何东西。在我看来,使用 DMA 可以加快速度。有问题的函数如下所示:

######### from file fatfs_sd.c #########
uint8_t SPI1_Transfer(uint8_t data){
    SPI1->CR1 |= SPI_CR1_SPE;               //enable SPI1
    SPI1->DR = data;                        // Write data to be transmitted to the SPI data register
    while (!(SPI1->SR & (SPI_SR_TXE)));     // Wait until transmit complete
    while (!(SPI1->SR & (SPI_SR_RXNE)));    // Wait until receive complete
    while (SPI1->SR & (SPI_SR_BSY));        // Wait until SPI is not busy anymore
    return SPI1->DR;                        // Return received data from SPI data register
}

static void SPI_TxByte(BYTE data){
    SPI1_Transfer(data);
}
static uint8_t SPI_RxByte(void){
    return SPI1_Transfer(0xff);
}

链接到更新的 .rar 存档

整个通讯

放大部分

这个问题也帮助了我: 如何减少 STM32L4 HAL 库的 SPI 开销时间

于 2020-12-29T18:25:24.393 回答