STM32F103 上的 FATFS R0.11 读取速度慢 - SPI

问题描述

我正在使用 STM32F103C8,我让 FATFS R0.11 运行良好(这是 CUBEMX 认在 STM32F103C8Tx 上使用的最新版本),但读取速度非常低,大约为 100 kB/s。

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

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

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

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

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

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

Link to .rar archive

从上到下:SCK-黄色、味噌-洋红色、MOSI-青色、CS-蓝色的。我添加了额外的延迟来显示传输的不同部分:第一个块负责安装和打开第一个文件,在 4 毫秒延迟后我打开第二个文件(延迟打开第一个文件没有造成任何延迟),然后在 2 毫秒后我执行第一次读取,并在额外的 2 毫秒延迟后,我读取了接下来的 2048 个字节。

Entirety of communication,added delays

Zoomed fragment

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

解决方法

好的,我想通了,你可以在上面的附图中清楚地看到,SPI总线上连续动作之间的延迟很长,这似乎是HAL做了很多开销工作的原因,这会减慢速度。我用自定义的函数替换了默认的发送和接收数据的函数,它在寄存器上做所有事情,读取时间减少了四倍,现在我可以在 5-6 毫秒内读取 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);
}

Link to updated .rar archive

Entirety of comm

Zoomed part

这个问题也帮助了我: How to decrease SPI overhead time for STM32L4 HAL library

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...