你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【HAL库每天一例】第047例: SPI-基于串行Flash的FatFS文件系统

[复制链接]
haohao663 发布时间:2016-6-21 10:11
【HAL库每天一例】系列例程从今天开始持续更新。。。。。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:https://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-047. SPI-基于串行Flash的FatFS文件系统
/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-047. SPI-基于串行Flash的FatFS文件系统
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:www ing10bbs com
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */

【1】例程简介
  串行Flash用于存储数据。YS-F1Pro开发板集成了一个16M字节的W25Q128串行Flash芯片,可以
用于存放数据。该芯片使用SPI1通信接口。
  FatFS是一个专门为嵌入式开发的开源小型文件系统。FatFS可以提供丰富的文件操作函数,方便
文件操作,我们可以在串行Flash空间上移植FatFS文件系统。

【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP1        PA10        TXD(CH340G)          已接入
  JP2        PA9         RXD(CH340G)          已接入
  
【3】操作及现象
使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱
动),在电脑端打开串口调试助手工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试
助手窗口可接收到信息。

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/


CubeMX_1.jpg
CubeMX_2.jpg
CubeMX_3.jpg
CubeMX_4.jpg
CubeMX_5.jpg



spiflash_diskio.c文件内容
  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: spiflash_diskio.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: 串行FLASH与FatFS文件系统桥接函数实现
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */

  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include <string.h>
  19. #include "ff_gen_drv.h"
  20. #include "spiflash/bsp_spiflash.h"

  21. /* 私有类型定义 --------------------------------------------------------------*/
  22. /* 私有宏定义 ----------------------------------------------------------------*/
  23. #define SPI_FLASH_REBUILD           1    // 1:使能格式化串行Flash,0:禁用格式化串行Flash
  24. #define SPI_FLASH_SECTOR_SIZE    4096    // 串行Flash扇区大小
  25. #define SPI_FLASH_START_SECTOR   1792    // 串行Flash文件系统FatFS偏移量
  26. #define SPI_FLASH_SECTOR_COUNT   2304    // 串行Flash文件系统FatFS占用扇区个数   



  27. /* 私有变量 ------------------------------------------------------------------*/
  28. static __IO DSTATUS Stat = STA_NOINIT;

  29. /* 扩展变量 ------------------------------------------------------------------*/
  30. /* 私有函数原形 --------------------------------------------------------------*/
  31. DSTATUS SPIFLASH_initialize(BYTE);
  32. DSTATUS SPIFLASH_status(BYTE);
  33. DRESULT SPIFLASH_read(BYTE, BYTE*, DWORD, UINT);

  34. #if _USE_WRITE == 1   // 如果允许写操作
  35.   DRESULT SPIFLASH_write (BYTE, const BYTE*, DWORD, UINT);
  36. #endif /* _USE_WRITE == 1 */

  37. #if _USE_IOCTL == 1   // 如果输入输出操作控制
  38.   DRESULT SPIFLASH_ioctl (BYTE, BYTE, void*);
  39. #endif  /* _USE_IOCTL == 1 */

  40. /* 定义串行FLASH接口函数 */
  41. const Diskio_drvTypeDef  SPIFLASH_Driver =
  42. {
  43.   SPIFLASH_initialize,                   // 串行FLASH初始化
  44.   SPIFLASH_status,                       // 串行FLASH状态获取
  45.   SPIFLASH_read,                         // 串行FLASH读数据
  46. #if  _USE_WRITE == 1
  47.   SPIFLASH_write,                        // 串行FLASH写数据
  48. #endif /* _USE_WRITE == 1 */
  49.   
  50. #if  _USE_IOCTL == 1
  51.   SPIFLASH_ioctl,                         // 获取串行FLASH信息
  52. #endif /* _USE_IOCTL == 1 */
  53. };

  54. /* 函数体 --------------------------------------------------------------------*/
  55. /**
  56.   * 函数功能: 串行FLASH初始化配置
  57.   * 输入参数: 无
  58.   * 返 回 值: 无
  59.   * 说    明: 无
  60.   */
  61. DSTATUS SPIFLASH_initialize(BYTE lun)
  62. {
  63. #if SPI_FLASH_REBUILD == 1
  64.   static uint8_t startflag=1;
  65. #endif
  66.   Stat = STA_NOINIT;
  67.   /* 初始化SPIFLASHIO外设 */
  68.   MX_SPIFlash_Init();
  69.   /* 获取串行FLASH状态 */
  70.   if(SPI_FLASH_ReadID()==SPI_FLASH_ID)
  71.   {
  72. #if SPI_FLASH_REBUILD == 1
  73.       if(startflag)
  74.       {
  75.         SPI_FLASH_SectorErase(SPI_FLASH_START_SECTOR*SPI_FLASH_SECTOR_SIZE);
  76.                           startflag=0;
  77.       }
  78. #endif
  79.     Stat &=~STA_NOINIT;
  80.   }
  81.   return Stat;
  82. }

  83. /**
  84.   * 函数功能: 串行FLASH状态获取
  85.   * 输入参数: lun : 不用
  86.   * 返 回 值: DSTATUS:串行FLASH状态返回值
  87.   * 说    明: 无
  88.   */
  89. DSTATUS SPIFLASH_status(BYTE lun)
  90. {
  91.   Stat = STA_NOINIT;

  92.   if(SPI_FLASH_ReadID()==SPI_FLASH_ID)
  93.   {
  94.     Stat &= ~STA_NOINIT;
  95.   }
  96.   return Stat;
  97. }

  98. /**
  99.   * 函数功能: 从串行FLASH读取数据到缓冲区
  100.   * 输入参数: lun : 不用
  101.   *           buff:存放读取到数据缓冲区指针
  102.   *           sector:扇区地址(LBA)
  103.   *           count:扇区数目
  104.   * 返 回 值: DSTATUS:操作结果
  105.   * 说    明: 无
  106.   */
  107. DRESULT SPIFLASH_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
  108. {
  109.   sector+=SPI_FLASH_START_SECTOR;      
  110.   SPI_FLASH_BufferRead(buff, sector*SPI_FLASH_SECTOR_SIZE, count*SPI_FLASH_SECTOR_SIZE);
  111.   return RES_OK;
  112. }

  113. /**
  114.   * 函数功能: 将缓冲区数据写入到串行FLASH内
  115.   * 输入参数: lun : 不用
  116.   *           buff:存放待写入数据的缓冲区指针
  117.   *           sector:扇区地址(LBA)
  118.   *           count:扇区数目
  119.   * 返 回 值: DSTATUS:操作结果
  120.   * 说    明: 无
  121.   */
  122. #if _USE_WRITE == 1
  123. DRESULT SPIFLASH_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
  124. {
  125.   uint32_t write_addr;
  126.   /* 扇区偏移7MB,外部Flash文件系统空间放在SPI Flash后面9MB空间 */
  127.   sector+=SPI_FLASH_START_SECTOR;
  128.   write_addr = sector*SPI_FLASH_SECTOR_SIZE;   
  129.   SPI_FLASH_SectorErase(write_addr);
  130.   SPI_FLASH_BufferWrite((uint8_t *)buff,write_addr,count*SPI_FLASH_SECTOR_SIZE);
  131.   return RES_OK;
  132. }
  133. #endif /* _USE_WRITE == 1 */

  134. /**
  135.   * 函数功能: 输入输出控制操作(I/O control operation)
  136.   * 输入参数: lun : 不用
  137.   *           cmd:控制命令
  138.   *           buff:存放待写入或者读取数据的缓冲区指针
  139.   * 返 回 值: DSTATUS:操作结果
  140.   * 说    明: 无
  141.   */
  142. #if _USE_IOCTL == 1
  143. DRESULT SPIFLASH_ioctl(BYTE lun, BYTE cmd, void *buff)
  144. {
  145.   DRESULT res = RES_ERROR;
  146.   
  147.   if (Stat & STA_NOINIT) return RES_NOTRDY;
  148.   
  149.   switch (cmd)
  150.   {
  151.   /* Make sure that no pending write process */
  152.   case CTRL_SYNC :
  153.     res = RES_OK;
  154.     break;
  155.   
  156.   /* 获取串行FLASH总扇区数目(DWORD) */
  157.   case GET_SECTOR_COUNT :
  158.     *(DWORD * )buff = SPI_FLASH_SECTOR_COUNT;       
  159.     res = RES_OK;
  160.     break;
  161.   
  162.   /* 获取读写扇区大小(WORD) */
  163.   case GET_SECTOR_SIZE :
  164.     *(WORD * )buff = SPI_FLASH_SECTOR_SIZE;
  165.     res = RES_OK;
  166.     break;
  167.   
  168.   /* 获取擦除块大小(DWORD) */
  169.   case GET_BLOCK_SIZE :
  170.     *(DWORD * )buff = 1;
  171.     res = RES_OK;
  172.     break;
  173.   
  174.   default:
  175.     res = RES_PARERR;
  176.   }
  177.   
  178.   return res;
  179. }
  180. #endif /* _USE_IOCTL == 1 */

  181. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
复制代码

diskio.c文件内容
  1. /*-----------------------------------------------------------------------*/
  2. /* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2014        */
  3. /*                                                                       */
  4. /*   Portions COPYRIGHT 2015 STMicroelectronics                          */
  5. /*   Portions Copyright (C) 2014, ChaN, all right reserved               */
  6. /*-----------------------------------------------------------------------*/
  7. /* If a working storage control module is available, it should be        */
  8. /* attached to the FatFs via a glue function rather than modifying it.   */
  9. /* This is an example of glue functions to attach various exsisting      */
  10. /* storage control modules to the FatFs module with a defined API.       */
  11. /*-----------------------------------------------------------------------*/
  12. /**
  13.   ******************************************************************************
  14.   * 文件名程: diskio.c
  15.   * 作    者: 硬石嵌入式开发团队
  16.   * 版    本: V1.0
  17.   * 编写日期: 2015-10-04
  18.   * 功    能: FatFS文件系统存储设备输入输出接口实现
  19.   ******************************************************************************
  20.   * 说明:
  21.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  22.   *
  23.   * 淘宝:
  24.   * 论坛:http://www.ing10bbs.com
  25.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  26.   ******************************************************************************
  27.   */

  28. /* 包含头文件 ----------------------------------------------------------------*/
  29. #include "diskio.h"
  30. #include "ff_gen_drv.h"
  31. #include "ff.h"

  32. #if _USE_LFN != 0   // 如果使能长文件名,添加相关解码文件

  33. #if _CODE_PAGE == 936        /* 简体中文:GBK */
  34. #include "option\cc936.c"
  35. #elif _CODE_PAGE == 950        /* 繁体中文:Big5 */
  36. #include "option\cc950.c"
  37. #else                                        /* Single Byte Character-Set */
  38. #include "option\ccsbcs.c"
  39. #endif

  40. #endif

  41. /* 私有类型定义 --------------------------------------------------------------*/
  42. /* 私有宏定义 ----------------------------------------------------------------*/
  43. /* 私有变量 ------------------------------------------------------------------*/
  44. /* 扩展变量 ------------------------------------------------------------------*/
  45. extern Disk_drvTypeDef  disk;

  46. /* 私有函数原形 --------------------------------------------------------------*/
  47. /* 函数体 --------------------------------------------------------------------*/
  48. /**
  49.   * 函数功能: 获取物理设备状态
  50.   * 输入参数: pdrv:物理设备编号
  51.   * 返 回 值: DSTATUS:操作结果
  52.   * 说    明: 无
  53.   */
  54. DSTATUS disk_status (
  55.         BYTE pdrv                /* Physical drive nmuber to identify the drive */
  56. )
  57. {
  58.   DSTATUS stat;
  59.   
  60.   stat = disk.drv[pdrv]->disk_status(disk.lun[pdrv]);
  61.   return stat;
  62. }

  63. /**
  64.   * 函数功能: 初始化物理设备
  65.   * 输入参数: pdrv:物理设备编号
  66.   * 返 回 值: DSTATUS:操作结果
  67.   * 说    明: 无
  68.   */
  69. DSTATUS disk_initialize (
  70.         BYTE pdrv                                /* Physical drive nmuber to identify the drive */
  71. )
  72. {
  73.   DSTATUS stat = RES_OK;
  74.   
  75.   if(disk.is_initialized[pdrv] == 0)
  76.   {
  77.     disk.is_initialized[pdrv] = 1;
  78.     stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
  79.   }
  80.   return stat;
  81. }

  82. /**
  83.   * 函数功能: 从物理设备读取数据到缓冲区
  84.   * 输入参数: pdrv:物理设备编号
  85.   *           buff:存放待写入数据的缓冲区指针
  86.   *           sector:扇区地址(LBA)
  87.   *           count:扇区数目(1..128)
  88.   * 返 回 值: DSTATUS:操作结果
  89.   * 说    明: 无
  90.   */
  91. DRESULT disk_read (
  92.         BYTE pdrv,                /* Physical drive nmuber to identify the drive */
  93.         BYTE *buff,                /* Data buffer to store read data */
  94.         DWORD sector, /* Sector address in LBA */
  95.         UINT count                /* Number of sectors to read */
  96. )
  97. {
  98.   DRESULT res;

  99.   res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
  100.   return res;
  101. }

  102. /**
  103.   * 函数功能: 将缓冲区数据写入到物理设备内
  104.   * 输入参数: pdrv:物理设备编号
  105.   *           buff:存放待写入数据的缓冲区指针
  106.   *           sector:扇区地址(LBA)
  107.   *           count:扇区数目
  108.   * 返 回 值: DSTATUS:操作结果
  109.   * 说    明: SD卡写操作没有使用DMA传输
  110.   */
  111. #if _USE_WRITE == 1
  112. DRESULT disk_write (
  113.         BYTE pdrv,                /* Physical drive nmuber to identify the drive */
  114.         const BYTE *buff,        /* Data to be written */
  115.         DWORD sector,                /* Sector address in LBA */
  116.         UINT count                /* Number of sectors to write */
  117. )
  118. {
  119.   DRESULT res;
  120.   
  121.   res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
  122.   return res;
  123. }
  124. #endif /* _USE_WRITE == 1 */

  125. /**
  126.   * 函数功能: 输入输出控制操作(I/O control operation)
  127.   * 输入参数: pdrv:物理设备编号
  128.   *           cmd:控制命令
  129.   *           buff:存放待写入或者读取数据的缓冲区指针
  130.   * 返 回 值: DSTATUS:操作结果
  131.   * 说    明: 无
  132.   */
  133. #if _USE_IOCTL == 1
  134. DRESULT disk_ioctl (
  135.         BYTE pdrv,                /* Physical drive nmuber (0..) */
  136.         BYTE cmd,                /* Control code */
  137.         void *buff                /* Buffer to send/receive control data */
  138. )
  139. {
  140.   DRESULT res;

  141.   res = disk.drv[pdrv]->disk_ioctl(disk.lun[pdrv], cmd, buff);
  142.   return res;
  143. }
  144. #endif /* _USE_IOCTL == 1 */

  145. /**
  146.   * 函数功能: 获取实时时钟
  147.   * 输入参数: 无
  148.   * 返 回 值: 实时时钟(DWORD)
  149.   * 说    明: 无
  150.   */
  151. __weak DWORD get_fattime (void)
  152. {
  153.           /* 返回当前时间戳 */
  154.         return          ((DWORD)(2015 - 1980) << 25)        /* Year 2015 */
  155.                         | ((DWORD)10 << 21)                                /* Month 10 */
  156.                         | ((DWORD)4  << 16)                                /* Mday 4 */
  157.                         | ((DWORD)10 << 11)                                /* Hour 10 */
  158.                         | ((DWORD)15 << 5)                                /* Min 15 */
  159.                         | ((DWORD)46 >> 1);                                /* Sec 46 */
  160. }

  161. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
复制代码

串口调试助手截图.jpg



收藏 3 评论21 发布时间:2016-6-21 10:11

举报

21个回答
guohaidao 回答时间:2016-6-21 15:53:59
Cube库虽然好用,不过Bug太多。有空可以试试看RTC的代码生成,连初始化都过不去,如何更好的让人使用呢?
yanhaijian 回答时间:2016-6-21 15:08:49
STM32CubeMX确实让开发变得更便利。
guohaidao 回答时间:2016-6-21 15:54:53
楼主有支持USB的MSD设备并实现FAT的工程吗?
haohao663 回答时间:2016-6-21 16:23:18
guohaidao 发表于 2016-6-21 15:53
Cube库虽然好用,不过Bug太多。有空可以试试看RTC的代码生成,连初始化都过不去,如何更好的让人使用呢? ...

RTC已经有例程的啦
【HAL库每天一例】第036例:RTC-实时时钟
https://www.stmcu.org.cn/module/ ... &fromuid=331315
(出处: 意法半导体STM32/STM8技术社区)
haohao663 回答时间:2016-6-21 16:26:39
guohaidao 发表于 2016-6-21 15:54
楼主有支持USB的MSD设备并实现FAT的工程吗?

手头上只有USB MSC例程(实现模拟U盘效果)
不知需要不?
guohaidao 回答时间:2016-6-22 11:29:08
haohao663 发表于 2016-6-21 16:26
手头上只有USB MSC例程(实现模拟U盘效果)
不知需要不?

需要,非常感谢:)
guohaidao 回答时间:2016-6-22 11:33:51
haohao663 发表于 2016-6-21 16:26
手头上只有USB MSC例程(实现模拟U盘效果)
不知需要不?

http://www.ing10bbs.com/forum.ph ... &extra=page%3D1
这个路径对吧。
guohaidao 回答时间:2016-6-22 11:35:20
最好有360云盘的分享链接,哈哈,毕竟360云盘比百度大。
haohao663 回答时间:2016-6-22 12:12:00
都是很大的,现在上传到360云盘
360云盘链接:http://yunpan.cn/OcPiRp3wEcA92u  访问密码 cfb6
上行网速不给力,等下午就可以下载
123下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版