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

FATFS R0.11 STM32F103上的慢速读取速度-SPI,stm32,sd-card,spi,fatfs,Stm32,Sd Card,Spi,Fatfs,我使用的是STM32F103C8,FATFS R0.11运行良好(默认情况下,这是CUBEMX在STM32F103C8Tx上使用的最新版本),但读取速度非常低,接近100 kB/s SPI时钟设置为18 MHz(从9 MHz更改,但没有区别,与4.5 MHz相反,4.5 MHz对读取速度的影响非常明显-读取时间增加了30%),我关闭了大多数额外选项以节省RAM。打开两个文件后,我剩下大约10KB(20KB)的RAM(在KEIL中编译时,STM32CUBEIDE使用了更多的RAM),这对于我项目的

我使用的是STM32F103C8,FATFS R0.11运行良好(默认情况下,这是CUBEMX在STM32F103C8Tx上使用的最新版本),但读取速度非常低,接近100 kB/s

SPI时钟设置为18 MHz(从9 MHz更改,但没有区别,与4.5 MHz相反,4.5 MHz对读取速度的影响非常明显-读取时间增加了30%),我关闭了大多数额外选项以节省RAM。打开两个文件后,我剩下大约10KB(20KB)的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卡)

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

我的SD卡适配器和连接:标准micro 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。它仍然很低,所以我将等待一段时间,看看是否有人对如何进一步改进有更好的想法。我还将FATF升级到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);
}

这个问题也帮助了我:

欢迎来到俱乐部。简单使用寄存器。它简单有效