历史上的今天
返回首页

历史上的今天

今天是:2024年09月16日(星期一)

2018年09月16日 | 使用STM32CUBEMX生成FatFS代码,操作SPI FLASH

2018-09-16 来源:eefocus

首先配置SPI,我的板子是SPI2连接到SPI FLASH 上,我的flash是W25Q64, PB12用来当CSN。

接下来配置FATFS,这里选择用户定义的。

配置FATFS的时候要注意,由于SPI FLASH 的sector是4096字节的,故需要设置sector的大小为4096,其余选项根据自己情况配置。

配置好了生成代码和工程。记得把堆栈尺寸调大一些。我用IAR这样配置:

接着把SPI FLASH的读写操作实现:读一个sector和写一个sector。我写好的函数叫做W25_WriteSector和W25_ReadSector. 然后定义好常量:

#define PAGE_SIZE       256

#define SECTOR_SIZE     4096

 

#define SECTOR_COUNT 200

#define BLOCK_SIZE 65536

#define FLASH_PAGES_PER_SECTOR SECTOR_SIZE/PAGE_SIZE

下一步打开user_diskio.c 文件,填充几个函数。


/**

  * @brief  Reads Sector(s) 

  * @param  pdrv: Physical drive number (0..)

  * @param  *buff: Data buffer to store read data

  * @param  sector: Sector address (LBA)

  * @param  count: Number of sectors to read (1..128)

  * @retval DRESULT: Operation result

  */

DRESULT USER_read (

BYTE pdrv,      /* Physical drive nmuber to identify the drive */

BYTE *buff,     /* Data buffer to store read data */

DWORD sector,   /* Sector address in LBA */

UINT count      /* Number of sectors to read */

)

{

  /* USER CODE HERE */

  UINT i = 0;

  for(i = 0; i < count; i ++)

  {

    W25_ReadSector(sector, buff);

    sector ++;

    buff += SECTOR_SIZE;

  }

  return RES_OK;

}


/**

  * @brief  Writes Sector(s)  

  * @param  pdrv: Physical drive number (0..)

  * @param  *buff: Data to be written

  * @param  sector: Sector address (LBA)

  * @param  count: Number of sectors to write (1..128)

  * @retval DRESULT: Operation result

  */

#if _USE_WRITE == 1

DRESULT USER_write (

BYTE pdrv,          /* Physical drive nmuber to identify the drive */

const BYTE *buff,   /* Data to be written */

DWORD sector,       /* Sector address in LBA */

UINT count          /* Number of sectors to write */

)

  /* USER CODE HERE */

  UINT i = 0;

  for(i = 0; i < count; i ++)

  {

    W25_WriteSector(sector, buff);

    sector ++;

    buff += SECTOR_SIZE;

  }

  return RES_OK;

}

#endif /* _USE_WRITE == 1 */


/**

  * @brief  I/O control operation  

  * @param  pdrv: Physical drive number (0..)

  * @param  cmd: Control code

  * @param  *buff: Buffer to send/receive control data

  * @retval DRESULT: Operation result

  */

#if _USE_IOCTL == 1

DRESULT USER_ioctl (

BYTE pdrv,      /* Physical drive nmuber (0..) */

BYTE cmd,       /* Control code */

void *buff      /* Buffer to send/receive control data */

)

{

  DRESULT res = RES_OK;

  

  switch(cmd)

  {

    case CTRL_SYNC :

        break;

 

    case CTRL_TRIM:

        break;

    case GET_BLOCK_SIZE:

*(DWORD*)buff = BLOCK_SIZE;

break;

    case GET_SECTOR_SIZE:

*(DWORD*)buff = SECTOR_SIZE;

        break;

    case GET_SECTOR_COUNT:

*(DWORD*)buff = SECTOR_COUNT;

break;

    default:

res = RES_PARERR;

break;

    }

  

  return res;

}

#endif /* _USE_IOCTL == 1 */


这些函数填充好,就可以用FATFS了。对于一个新的SPI FLASH,先挂载f_mount,再格式化文件系统f_mkfs,之后就可以做各种新建文件、读写操作了。

补充一个,在fatfs.c 文件中,定义了这样一个:


char USER_Path[4];  /* USER logical drive path */


之后我们可以在main或者其他文件里用extern声明它,mount和mkfs时的USER_Path都是它。

附上我的测试代码


void mount_disk(void)

{

  uint8_t res = f_mount(&fs, USER_Path, 0);

  if (res != FR_OK)

  {

    printf("FAILED: %d\n",res);

   return;

 }

  printf("MOUNT OK\n");

}

 

void format_disk(void)

{

  uint8_t res = 0;

      

  printf("PROCESSING...\n");

  res = f_mkfs(USER_Path, 1, 4096);

  if (res == FR_OK)

  {

    printf("OK!\n");

  }

  else

  {

    printf("failed with: %d\n",res);

  }

}

 

void create_file(void)

{

  FIL file;

  FIL *pf = &file;

  uint8_t res;

  res = f_open(pf, "0:/test.txt", FA_OPEN_ALWAYS | FA_WRITE);

  if (res == FR_OK)

  {

    printf("creat ok\n");

  }

  else

  {

    printf("creat failed\n");

    printf("error code: %d\n",res);

  }

  

  f_printf(pf, "hello fatfs!\n");

  

  res = f_close(pf);

    if (res != FR_OK)

    {

      printf("close file error\n");

      printf("error code: %d\n",res);

    }

}

 

void get_disk_info(void)

{

FATFS fs;

FATFS *fls = &fs;

FRESULT res;

DWORD fre_clust;

 

res = f_getfree("/",&fre_clust,&fls);         /* Get Number of Free Clusters */

if (res == FR_OK) 

{

                                            /* Print free space in unit of MB (assuming 4096 bytes/sector) */

        printf("%d KB Total Drive Space.\n"

               "%d KB Available Space.\n",

               ((fls->n_fatent-2)*fls->csize)*4,(fre_clust*fls->csize)*4);

}

else

{

printf("get disk info error\n");

printf("error code: %d\n",res);

}   

}

 

void read_file(void)

{

  FIL file;

  FRESULT res;

  UINT bw;

  uint8_t rbuf[100] = {0};

  

  res = f_open(&file, "0:/test.txt", FA_READ);

  if (res != FR_OK)

  {

    printf("open error: %d\n",res);

    return;

  }

  f_read(&file, rbuf, 20, &bw);

  printf("%s\n", rbuf);

  

  res = f_close(&file);

  if (res != FR_OK)

  {

     printf("close file error\n");

     printf("error code: %d\n",res);

  }

}


推荐阅读

史海拾趣

南晶电子(DGNJDZ)公司的发展小趣事

随着市场竞争的加剧,南晶电子意识到技术创新是企业发展的核心动力。公司投入大量研发资金,与多所高校和科研机构建立合作关系,共同研发新型半导体器件。经过不懈努力,南晶电子成功推出了一系列具有自主知识产权的高性能产品,赢得了市场的广泛认可。

HALO Electronics公司的发展小趣事

随着市场竞争的加剧,南晶电子意识到技术创新是企业发展的核心动力。公司投入大量研发资金,与多所高校和科研机构建立合作关系,共同研发新型半导体器件。经过不懈努力,南晶电子成功推出了一系列具有自主知识产权的高性能产品,赢得了市场的广泛认可。

Cliff Electronic Components公司的发展小趣事

随着人工智能、物联网等技术的快速发展,南晶电子意识到传统半导体器件已无法满足市场需求。公司决定进行转型升级,向智能穿戴设备、智能家居、汽车电子等领域拓展。通过引进先进技术和设备,加强研发团队建设,南晶电子成功推出了一系列智能化产品,实现了从传统制造业向智能制造的转型。

DuPont公司的发展小趣事

随着全球环保意识的提高,对于环保型电子材料的需求也日益增长。DuPont公司积极响应这一趋势,致力于环保型电子材料的研发和生产。公司采用先进的环保技术和生产工艺,开发出了一系列低污染、低能耗的电子材料。这些材料不仅具有良好的性能,而且对环境友好,符合可持续发展的要求。DuPont公司的这一举措,不仅提升了公司的竞争力,也为电子行业的可持续发展做出了积极贡献。

台湾富晶(FORTUNE)公司的发展小趣事
使用示波器等工具检查时钟信号的波形和频率是否正常。
CyOptics Inc公司的发展小趣事

除了数据通讯和电信市场外,CyOptics的光学产品还逐渐拓展至其他领域。例如,公司的光学组件已集成至光学收发器、转发器及线卡等设备中,为数据中心、高性能计算和企业存储网络等应用提供了强有力的支持。此外,CyOptics还积极开拓新兴市场,如数据库、地铁及长途干线市场等,为客户提供定制化的光学解决方案。

问答坊 | AI 解惑

5口以太网交换机原理图

哥们今天刚按照实物反推出的,主芯片为DM9081的5口以太网交换机原理图.PROTEL99SE格式. [ 本帖最后由 西门 于 2009-5-12 18:31 编辑 ]…

查看全部问答>

关于OP07

哪位可以给我讲讲这电路上面的二极管是什么作用啊,特别是为什么要在OP07反馈和输出端加上IN4148…

查看全部问答>

一种用N+1条线实现矩阵键盘的方法

键盘输入作为最常用的输入设备仍有其不可替代的作用。下面首先对传统键盘作一个简单的介绍。 (1)传统键盘的介绍键盘的结构通常有两种形式:线性键盘和矩阵键盘。在不同的场合下,这两种键盘均得到了广泛的应用。线性键盘由若干个独立的按键组成, ...…

查看全部问答>

Platform Builder 4.2中自带的S3C2410BSP可以用于S3C2440么?

Platform Builder 4.2中自带的S3C2410 BSP可以用于S3C2440么? 或者哪里有下载用于S3C2440 BSP for PB4.2的?…

查看全部问答>

ST-LINKII可以支持MDK了

ST-LINK-II 可以支持MDK使用了!MDK3.22中文版已经在realview网站上发布了,里面已经集成了支持ST-LINKII的驱动,下载安装后就可以配合ST-LINKII使用。下载地址:http://www.realview.com.cn/down-list.asp?id=487…

查看全部问答>

我做了一块485通讯板子,帮我看看?

     专业做单片机软硬件开发                地址:哈尔滨市 南岗区 会展中心             ...…

查看全部问答>

请教:TI的M4单片机中的自带ROM里的程序是出厂就烧制好的吗?

用户自己能不能更改这个ROM内容,或者供用户使用?…

查看全部问答>

UDA1341驱动问题

有人用FPGA驱动过UDA1341吗?UDA1341芯片的L3MODE,L3CLOCK.L3DATA三个信号引脚对AD,DA有影响吗?…

查看全部问答>

ADuC7061中断方式实现串口通信

/******************************* * name: * function: * return: ********************************/ #include \"string.h\" #include \"global.h\" #include \"function.h\" #include #include unsigned char UartDataRecevice; un ...…

查看全部问答>

有人熟悉这块单片机板子么?Inter 8086的

在大四毕业季后,俺和同学去淘学长们遗留的“废品”。得此物,一查PDF,什么上世纪70年代的PDF,板子上印的是2009年做的。茫然呀…

查看全部问答>