【国民技术低功耗系列N32L43x测评】4、SPI-FLASH驱动+fatfs文件系统移植+USB驱动模...
本帖最后由 emmnn 于 2022-7-26 17:02 编辑# 前言
距离上篇帖子过去也有两个星期的时间了,今天主要分享的内容是W25Q128 SPI-FLASH的驱动,以及如何通过usb驱动的移植,实现SPI-FLASH模拟U盘的功能。在移植好的SPI-FLASH上,我们可以很方便的通过电脑的USB接口存储我们项目开发所需要的字库文件,ui图片资源文件等,从而解决因片上flash空间不够而无法存储项目所需资源文件的问题。
# 一、SPI-FLASH (W25Q128驱动)
引脚定义
引脚功能说明
首先是SPI-FLASH(W25Q128)驱动,关于这部分的驱动代码,在网上可以找到很多,我这边是直接把野火的源码拷贝过来更改使用的,以下是源码中关于引脚定义及初始化部分(完整源码请查看附件)
```c
//#definesFLASH_ID 0xEF3015 //W25X16
//#definesFLASH_ID 0xEF4015 //W25Q16
#definesFLASH_ID 0XEF4018 //W25Q128
//#definesFLASH_ID 0XEF4017 //W25Q64
#define SPI_FLASH_PERIPH SPI1
#define SPI_FLASH_RCC_PERIPH RCC_APB2_PERIPH_SPI1
#define SPI_FLASH_GPIO_PERIPH RCC_APB2_PERIPH_GPIOA
//SCK引脚
#define SPI_FLASH_SCK_PORT GPIOA
#define SPI_FLASH_SCK_PIN GPIO_PIN_5
//MOSI引脚
#define SPI_FLASH_MOSI_PORT GPIOA
#define SPI_FLASH_MOSI_PIN GPIO_PIN_7
//MISO引脚
#define SPI_FLASH_MISO_PORT GPIOA
#define SPI_FLASH_MISO_PIN GPIO_PIN_6
//CS(NSS)引脚 片选选普通GPIO即可
#define SPI_FLASH_CS_PORT GPIOA
#define SPI_FLASH_CS_PIN GPIO_PIN_4
#define SPI_FLASH_CS_LOW() SPI_FLASH_CS_PORT->PBC = SPI_FLASH_CS_PIN
#define SPI_FLASH_CS_HIGH() SPI_FLASH_CS_PORT->PBSC = SPI_FLASH_CS_PIN
```
```c
/**
* @briefSPI_FLASH初始化
* @param无
* @retval 无
*/
void SPI_FLASH_Init(void)
{
GPIO_InitType GPIO_InitStructure;
SPI_InitType SPI_InitStructure;
/* Enable the GPIO Clock */
RCC_EnableAPB2PeriphClk(SPI_FLASH_GPIO_PERIPH|RCC_APB2_PERIPH_AFIO, ENABLE);
/*!< SPI1 Periph clock enable */
RCC_EnableAPB2PeriphClk(SPI_FLASH_RCC_PERIPH, ENABLE);
/* Configure the GPIO pin */
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = SPI_FLASH_CS_PIN;
GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_InitPeripheral(SPI_FLASH_CS_PORT, &GPIO_InitStructure);
/*!< Configure SPI1 pins: SCK */
GPIO_InitStructure.Pin = SPI_FLASH_SCK_PIN;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
GPIO_InitPeripheral(SPI_FLASH_SCK_PORT, &GPIO_InitStructure);
/*!< Configure SPI1 pins: MOSI */
GPIO_InitStructure.Pin = SPI_FLASH_MOSI_PIN;
GPIO_InitPeripheral(SPI_FLASH_MOSI_PORT, &GPIO_InitStructure);
/*!< Configure SPI1 pins: MISO */
GPIO_InitStructure.Pin = SPI_FLASH_MISO_PIN;
GPIO_InitPeripheral(SPI_FLASH_MISO_PORT, &GPIO_InitStructure);
/* 停止信号 FLASH: CS引脚高电平*/
SPI_FLASH_CS_HIGH();
/*!< SPI configuration */
SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_2;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly= 7;
SPI_Init(SPI_FLASH_PERIPH, &SPI_InitStructure);
/*!< Enable the SPI_PERIPH*/
SPI_Enable(SPI_FLASH_PERIPH, ENABLE);
}
```
# 二、fatfs文件系统移植
搞定SPI-FLASH的驱动程序后,接下来要弄的就是文件系统的移植。fatfs是一款通用的文件系统,被广泛地应用在小型的嵌入式系统中。fatfs具有代码量少,占用资源量小,可移植性高等特点,因此在嵌入式设备中被广泛使用。
fatfs下载链接:(http://elm-chan.org/fsw/ff/00index_e.htmll)
在官网上可以看到,目前该版本已更新到R0.14b,我们就以这个版本为基准简单介绍下该文件系统的移植。
下载后解压缩,有两个文件夹documents和source,fatfs源码就在source目录下。
将所有.c文件添加到我们的工程项目中,同时配置好编译路径。
源码文件我们只需要更改diskio.c这个文件就可以了,更改如下:
```c
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
#include "bsp_spi_flash.h"
/* Definitions of physical drive number for each drive */
#define DEV_SPI_FLASH 0 /* Map SPI_FLASH to physical drive 0 */
#define FLASH_SECTOR_SIZE 512
#define FLASH_BLOCK_SIZE 8
#define FLASH_SECTOR_COUNT 2048*16
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat = STA_NOINIT;
if (pdrv == DEV_SPI_FLASH)
{
/* SPI Flash状态检测:读取SPI Flash 设备ID */
if(sFLASH_ID == SPI_FLASH_ReadID())
{
/* 设备ID读取结果正确 */
stat &= ~STA_NOINIT;
}
else
{
/* 设备ID读取结果错误 */
stat = STA_NOINIT;
}
}
return stat;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat = STA_NOINIT;
uint16_t i;
if (pdrv == DEV_SPI_FLASH)
{
/* 初始化SPI Flash */
SPI_FLASH_Init();
/* 延时一小段时间 */
i=500;
while(--i);
/* 唤醒SPI Flash */
SPI_Flash_WAKEUP();
/* 获取SPI Flash芯片状态 */
stat=disk_status(pdrv);
}
return stat;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res = RES_PARERR;
if (pdrv == DEV_SPI_FLASH)
{
while(count--)
{
SPI_FLASH_BufferRead(buff, sector*FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE);
sector++;
buff+=FLASH_SECTOR_SIZE;
}
res = RES_OK;
}
return res;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if FF_FS_READONLY == 0
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res = RES_PARERR;
if (pdrv == DEV_SPI_FLASH)
{
while(count --)
{
SPI_FLASH_SectorErase(sector*FLASH_SECTOR_SIZE);
SPI_FLASH_BufferWrite((uint8_t *)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
sector++;
buff+=FLASH_SECTOR_SIZE;
}
res = RES_OK;
}
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res = RES_PARERR;
if (pdrv == DEV_SPI_FLASH)
{
switch (cmd)
{
case CTRL_SYNC:
break;
case GET_SECTOR_COUNT:
*(DWORD * )buff = FLASH_SECTOR_COUNT;
break;
/* 扇区大小*/
case GET_SECTOR_SIZE :
*(WORD * )buff = FLASH_SECTOR_SIZE;
break;
/* 同时擦除扇区个数 */
case GET_BLOCK_SIZE :
*(DWORD * )buff = FLASH_BLOCK_SIZE;
break;
}
res = RES_OK;
}
return res;
}
__weak DWORD get_fattime(void) {
/* 返回当前时间戳 */
return ((DWORD)(2015 - 1980) << 25) /* Year 2015 */
| ((DWORD)1 << 21) /* Month 1 */
| ((DWORD)1 << 16) /* Mday 1 */
| ((DWORD)0 << 11) /* Hour 0 */
| ((DWORD)0 << 5) /* Min 0 */
| ((DWORD)0 >> 1); /* Sec 0 */
}
```
此外还有ffconf.h文件,这个文件都是一些宏定义,可根据我们的需要去更改对应的宏来开启或关闭相应的功能,这里我们主要更改下面这两个地方
```c
#define FF_USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 936
/* This option specifies the OEM code page to be used on the target system.
/Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
```
最后我们可以写下测试代码测试下移植后的功能
```c
#if 1
/*----------------------- 格式化测试 -----------------*/
/* 如果没有文件系统就格式化创建创建文件系统 */
if(res_flash == FR_NO_FILESYSTEM)
{
/* 格式化 */
res_flash = f_mkfs("0:", 0, work, sizeof(work));
if(res_flash == FR_OK)
{
PRO_LOG(LOG_DEBUG, "f_mkfs success. \r\n");
/* 格式化后,先取消挂载 */
res_flash = f_mount(NULL,"0:",1);
/* 重新挂载 */
res_flash = f_mount(&fs,"0:",1);
}
else
{
PRO_LOG(LOG_DEBUG, "f_mkfs failed.\r\n");
}
}
else if(res_flash!=FR_OK)
{
PRO_LOG(LOG_DEBUG, "f_mount failed. (%d). \r\n", res_flash);
}
else
{
PRO_LOG(LOG_DEBUG, "f_mount init success, then start write and read test. \r\n");
}
/*----------------------- 写测试 -----------------*/
/* 打开文件,每次都以新建的形式打开,属性为可写 */
PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START WRITE... ******\r\n");
if(!f_open(&fp,"0:你好.txt",FA_CREATE_ALWAYS | FA_WRITE))
{
PRO_LOG(LOG_DEBUG, "open file success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "open file failure!\n");
}
if(!f_write(&fp,(char*)write_text,strlen(write_text),&write_bytes))
{
PRO_LOG(LOG_DEBUG, "write success,write_bytes=%d\n",write_bytes);
}
else
{
PRO_LOG(LOG_DEBUG, "write failure!\n");
}
if(!f_close(&fp))
{
PRO_LOG(LOG_DEBUG, "close success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "close failure!\n");
}
/*----------------------- 读测试 -----------------*/
PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START READ... ******\r\n");
if(!f_open(&fp,"0:你好.txt",FA_READ))
{
PRO_LOG(LOG_DEBUG, "open file success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "open file failure!\n");
}
if(!f_read(&fp,(char*)read_buff,sizeof(read_buff),&read_bytes))
{
PRO_LOG(LOG_DEBUG, "read success,read_bytes=%d\n",read_bytes);
PRO_LOG(LOG_DEBUG, "test.txt content is :%s\n",read_buff);
}
else
{
PRO_LOG(LOG_DEBUG, "read failure!\n");
}
if(!f_close(&fp))
{
PRO_LOG(LOG_DEBUG, "close success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "close failure!\n");
}
#endif
```
编译烧录,上电运行:
# 三、usb--SPI-FLASH模拟U盘
关于USB驱动的移植,国民技术官方也有提供移植好的例程供我们参考,官方提供的例程是通过USB访问片上flash的,我们只需要把官方的例程拿过来稍微改下
将USB-lib添加到我们的工程中
将USB-DEVICE部分代码拷贝到我们工程中,一个文件夹统一管理
更改mass_mal.c文件
```c
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ****************************************************************************/
/**
* @file mass_mal.c
* @author Nations
* @version v1.0.0
*
* @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
*/
/* Includes ------------------------------------------------------------------*/
#include "mass_mal.h"
#include "n32l43x_flash.h"
#include "bsp_spi_flash.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FLASH_SECTOR_SIZE 512
#define FLASH_BLOCK_SIZE 8
#define FLASH_SECTOR_COUNT 2048*16
#define sFLASH_ID 0XEF4018 //W25Q128
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t Mass_Memory_Size;
uint32_t Mass_Block_Size;
uint32_t Mass_Block_Count;
/* logic unit count; the first is 0 */
uint32_t Max_Lun = 0;
/**
* @brief Initializes the Media on the Nations.
* @param lun: logical unit.
* @returnMAL_FAIL.
*/
uint16_t MAL_Init(uint8_t lun)
{
uint16_t status = MAL_OK;
SPI_FLASH_Init();
if(SPI_FLASH_ReadID()==sFLASH_ID)
{
//printf("flash init succsee\n");
status = MAL_OK;
}
else
status = MAL_FAIL;
return status;
}
/**
* @brief Write sectors.
* @param lun: logical unit.
* @param Memory_Offset: memory offset.
* @param Writebuff: write buff pointer.
* @param Transfer_Length: transfer data length.
* @returnMAL_OK or MAL_FAIL.
*/
uint16_t MAL_Write(uint8_t lun, uint32_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length)
{
uint16_t i;
switch (lun)
{
case 0:
W25QXX_Write((uint8_t*)Writebuff, Memory_Offset, Transfer_Length);
break;
case 1:
break;
default:
return MAL_FAIL;
}
return MAL_OK;
}
/**
* @brief Write sectors.
* @param lun: logical unit.
* @param Memory_Offset: memory offset.
* @param Readbuff: read buff pointer.
* @param Transfer_Length: transfer data length.
* @returnMAL_OK or MAL_FAIL.
*/
uint16_t MAL_Read(uint8_t lun, uint32_t Memory_Offset, uint32_t *Readbuff, uint16_t Transfer_Length)
{
uint16_t i;
switch (lun)
{
case 0:
SPI_FLASH_BufferRead((uint8_t *)Readbuff, Memory_Offset, Transfer_Length);
break;
case 1:
break;
default:
return MAL_FAIL;
}
return MAL_OK;
}
/**
* @brief Get status.
* @param lun: logical unit.
* @returnMAL_OK or MAL_FAIL.
*/
uint16_t MAL_GetStatus (uint8_t lun)
{
if (lun == 0)
{
Mass_Block_Count = FLASH_SECTOR_COUNT;
Mass_Block_Size =FLASH_SECTOR_SIZE;
Mass_Memory_Size = FLASH_SECTOR_COUNT*FLASH_SECTOR_SIZE;
return MAL_OK;
}
return MAL_FAIL;
}
```
中断处理
```c
/**
* @briefThis function handles USB_LP_IRQHandler Handler.
*/
void USB_LP_IRQHandler(void)
{
USB_Istr();
}
```
测试代码
```c
FATFS fs;//文件系统对象
FIL fp;//文件对象
char *write_text="FATFS test success!";
unsigned int write_bytes=0;
char read_buff;
unsigned int read_bytes=0;
BYTE work;
static void main_thread_entry(void * para)
{
FRESULT res_flash;
res_flash = f_mount(&fs,"0:",1);
#if 1
/*----------------------- 格式化测试 -----------------*/
/* 如果没有文件系统就格式化创建创建文件系统 */
if(res_flash == FR_NO_FILESYSTEM)
{
/* 格式化 */
res_flash = f_mkfs("0:", 0, work, sizeof(work));
if(res_flash == FR_OK)
{
PRO_LOG(LOG_DEBUG, "f_mkfs success. \r\n");
/* 格式化后,先取消挂载 */
res_flash = f_mount(NULL,"0:",1);
/* 重新挂载 */
res_flash = f_mount(&fs,"0:",1);
}
else
{
PRO_LOG(LOG_DEBUG, "f_mkfs failed.\r\n");
}
}
else if(res_flash!=FR_OK)
{
PRO_LOG(LOG_DEBUG, "f_mount failed. (%d). \r\n", res_flash);
}
else
{
PRO_LOG(LOG_DEBUG, "f_mount init success, then start write and read test. \r\n");
}
/*----------------------- 写测试 -----------------*/
/* 打开文件,每次都以新建的形式打开,属性为可写 */
PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START WRITE... ******\r\n");
if(!f_open(&fp,"0:test.txt",FA_CREATE_ALWAYS | FA_WRITE))
{
PRO_LOG(LOG_DEBUG, "open file success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "open file failure!\n");
}
if(!f_write(&fp,(char*)write_text,strlen(write_text),&write_bytes))
{
PRO_LOG(LOG_DEBUG, "write success,write_bytes=%d\n",write_bytes);
}
else
{
PRO_LOG(LOG_DEBUG, "write failure!\n");
}
if(!f_close(&fp))
{
PRO_LOG(LOG_DEBUG, "close success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "close failure!\n");
}
/*----------------------- 读测试 -----------------*/
PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START READ... ******\r\n");
if(!f_open(&fp,"0:test.txt",FA_READ))
{
PRO_LOG(LOG_DEBUG, "open file success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "open file failure!\n");
}
if(!f_read(&fp,(char*)read_buff,sizeof(read_buff),&read_bytes))
{
PRO_LOG(LOG_DEBUG, "read success,read_bytes=%d\n",read_bytes);
PRO_LOG(LOG_DEBUG, "test.txt content is :%s\n",read_buff);
}
else
{
PRO_LOG(LOG_DEBUG, "read failure!\n");
}
if(!f_close(&fp))
{
PRO_LOG(LOG_DEBUG, "close success!\n");
}
else
{
PRO_LOG(LOG_DEBUG, "close failure!\n");
}
#endif
if(USB_Config(SYSCLK_VALUE_96MHz) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
rt_thread_delay(50);
}
}
while(1)
{
rt_thread_delay(1000);
}
}
```
这里还有个地方需要注意下,在调USB这块驱动时,网上看到相关资料说这一块的时钟必须配置成不大于48MHz(有些说必须配置成48MHz,所以我这边就直接给配置成48MHz了),因此时钟这一块也需要重新配置下,具体配置可以看源码。
可以看到我们移植后基本是OK的。
# 四、问题点总结
最后就是问题点的总结,暂时也还没花时间去搞明白,要是有熟悉这方面的朋友希望能指点下:
**问题1:**我在我的程序中创建一个中文名文件时,在pc端查看,中文名会变成乱码;
**问题2:**在测试过程中发现,我通过USB往flash写入文件(就是往flash里面拉文件),这速度非常缓慢(只有几十kb/s),用官方的例程测试速度有1-2M/s,当然官方的例程写片上的flash是会快一点的,想问下有人知道这部分怎么优化。:tw-Ac2:
#附件
最后,附件如下
<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/loveliness.gif" width="48" />这个usb速度的问题,是不是和你那种类似 @RCSN </p>
<p>第一个问题,应该是Fatfs文件系统的问题,可以参考下网上的做法,转下格式</p>
<p>第二个问题,我理解你是USB先传输文件到mcu,不是知道是ram还是片上flash,然后再通过spi传输到W25Q128。那这样的话,放到mcu ram中是比较好点的,另外spi速率提高看看,剩下的部分就是逻辑上的优化了,包括但不局限于提升软件优化等级,直接操作寄存器等方式。</p>
沧桑小草 发表于 2022-8-1 22:57
第一个问题,应该是Fatfs文件系统的问题,可以参考下网上的做法,转下格式
第二个问题,我理解你是USB先 ...
<p>感谢指导,抽时间会再看看这个问题,最近一段时间较忙,后续解决了会继续发帖补充解决方法<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/handshake.gif" width="48" /></p>
页:
[1]