微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 第044例: SDIO-基于SD卡FatFS文件系统

第044例: SDIO-基于SD卡FatFS文件系统

时间:10-02 整理:3721RD 点击:
【HAL库每天一例】系列例程从今天开始持续更新。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:http://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)YSF1_HAL-043. SDIO-SD卡读写)
/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-044. SDIO-基于SD卡FatFS文件系统
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:www.ing10bbs.com
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */
【1】例程简介
  SDIO是安全输入输出接口,采用在SD卡上。SD卡做为一种性价比极高的存储介质,在生活中非常
普遍可见。
  上个例程是直接对SD卡进行读写操作,一般使用SD卡都需要通过文件系统,使得类似电脑操作文件
一样简单明了。
  FatFS是一个专门为嵌入式开发的开源小型文件系统。
  本例程移植FatFS,实现SD卡文件读写。
  
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP1        PA10        TXD(CH340G)          已接入
  JP2        PA9         RXD(CH340G)          已接入
  
【3】操作及现象
  将一张小于32G大小的Micro SD卡插入到开发板上的SD卡槽内,使用开发板配套的MINI USB线连
接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱动),在电脑端打开串口调试助手
工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试助手窗口可接收到信息。
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/












bsp_sdcard.c文件内容

  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: bsp_sdcard.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: SD卡底层驱动实现
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */

  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include "sdio/bsp_sdcard.h"

  19. /* 私有类型定义 --------------------------------------------------------------*/
  20. /* 私有宏定义 ----------------------------------------------------------------*/
  21. /* 私有变量 ------------------------------------------------------------------*/
  22. SD_HandleTypeDef hsdcard;
  23. HAL_SD_CardInfoTypedef SDCardInfo;
  24. DMA_HandleTypeDef hdma_sdio;

  25. /* 扩展变量 ------------------------------------------------------------------*/
  26. /* 私有函数原形 --------------------------------------------------------------*/
  27. /* 函数体 --------------------------------------------------------------------*/
  28. /**
  29.   * 函数功能: SD卡初始化配置
  30.   * 输入参数: 无
  31.   * 返 回 值: 无
  32.   * 说    明: 无
  33.   */
  34. void MX_SDIO_SD_Init(void)
  35. {
  36.   hsdcard.Instance = SDIO;
  37.   hsdcard.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  38.   hsdcard.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  39.   hsdcard.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  40.   hsdcard.Init.BusWide = SDIO_BUS_WIDE_1B;
  41.   hsdcard.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  42.   hsdcard.Init.ClockDiv = 2;
  43.   HAL_SD_Init(&hsdcard, &SDCardInfo);
  44.   
  45.   HAL_SD_WideBusOperation_Config(&hsdcard, SDIO_BUS_WIDE_4B); // 设置为4bit SDIO
  46. }

  47. /**
  48.   * 函数功能: SDIO外设初始化配置
  49.   * 输入参数: hsd:SDIO句柄类型指针
  50.   * 返 回 值: 无
  51.   * 说    明: 该函数被HAL库内部调用
  52.   */
  53. void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
  54. {
  55.   GPIO_InitTypeDef GPIO_InitStruct;
  56.   if(hsd->Instance==SDIO)
  57.   {
  58.     /* 使能SDIO外设时钟*/
  59.     __HAL_RCC_SDIO_CLK_ENABLE();
  60.    
  61.     /* Enable DMA2 clocks */
  62.     __HAL_RCC_DMA2_CLK_ENABLE();
  63.    
  64.     /* 使能GPIO端口时钟 */
  65.     __HAL_RCC_GPIOC_CLK_ENABLE();
  66.     __HAL_RCC_GPIOD_CLK_ENABLE();
  67.    
  68.     /**SDIO GPIO Configuration   
  69.     PC8     ------> SDIO_D0
  70.     PC9     ------> SDIO_D1
  71.     PC10     ------> SDIO_D2
  72.     PC11     ------> SDIO_D3
  73.     PC12     ------> SDIO_CK
  74.     PD2     ------> SDIO_CMD
  75.     */
  76.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
  77.                           |GPIO_PIN_12;
  78.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  79.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  80.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  81.     GPIO_InitStruct.Pin = GPIO_PIN_2;
  82.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  83.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  84.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  85.    
  86.     /* 配置DMA传输:读SD卡内容时使用 */  
  87.     hdma_sdio.Instance = DMA2_Channel4;
  88.     hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
  89.     hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
  90.     hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
  91.     hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  92.     hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  93.     hdma_sdio.Init.Mode = DMA_NORMAL;
  94.     hdma_sdio.Init.Priority = DMA_PRIORITY_HIGH;
  95.     HAL_DMA_Init(&hdma_sdio);
  96.    
  97.     /* 链接SDIO的DMA接收 */
  98.     __HAL_LINKDMA(hsd,hdmarx,hdma_sdio);
  99.    
  100.     /* SDIO外设中断配置 */
  101.     HAL_NVIC_SetPriority(SDIO_IRQn, 0, 1);
  102.     HAL_NVIC_EnableIRQ(SDIO_IRQn);
  103.    
  104.     /* DMA中断配置 */
  105.     HAL_NVIC_SetPriority(DMA2_Channel4_5_IRQn, 0, 2);
  106.     HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
  107.   }
  108. }

  109. /**
  110.   * 函数功能: SDIO外设反初始化配置
  111.   * 输入参数: hsd:SDIO句柄类型指针
  112.   * 返 回 值: 无
  113.   * 说    明: 该函数被HAL库内部调用
  114.   */
  115. void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd)
  116. {
  117.   if(hsd->Instance==SDIO)
  118.   {
  119.     /* 禁用SDIO时钟 */
  120.     __HAL_RCC_SDIO_CLK_DISABLE();
  121.   
  122.     /**SDIO GPIO Configuration   
  123.     PC8     ------> SDIO_D0
  124.     PC9     ------> SDIO_D1
  125.     PC10     ------> SDIO_D2
  126.     PC11     ------> SDIO_D3
  127.     PC12     ------> SDIO_CK
  128.     PD2     ------> SDIO_CMD
  129.     */
  130.     HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
  131.                           |GPIO_PIN_12);

  132.     HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
  133.    
  134.     /* Peripheral DMA DeInit*/
  135.     HAL_DMA_DeInit(hsd->hdmarx);
  136.    
  137.     /* 关闭中断 */
  138.     HAL_NVIC_DisableIRQ(SDIO_IRQn);
  139.     HAL_NVIC_DisableIRQ(DMA2_Channel4_5_IRQn);
  140.   }
  141. }

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

复制代码


sd_diskio.c文件内容

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

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

  21. /* 私有类型定义 --------------------------------------------------------------*/
  22. /* 私有宏定义 ----------------------------------------------------------------*/
  23. #define BLOCK_SIZE                512

  24. /* 私有变量 ------------------------------------------------------------------*/
  25. static volatile DSTATUS Stat = STA_NOINIT;


  26. /* 扩展变量 ------------------------------------------------------------------*/
  27. /* 私有函数原形 --------------------------------------------------------------*/
  28. DSTATUS SD_initialize (BYTE);
  29. DSTATUS SD_status (BYTE);
  30. DRESULT SD_read (BYTE, BYTE*, DWORD, UINT);

  31. #if _USE_WRITE == 1   // 如果允许写操作
  32.   DRESULT SD_write (BYTE, const BYTE*, DWORD, UINT);
  33. #endif /* _USE_WRITE == 1 */

  34. #if _USE_IOCTL == 1   // 如果输入输出操作控制
  35.   DRESULT SD_ioctl (BYTE, BYTE, void*);
  36. #endif  /* _USE_IOCTL == 1 */

  37. /* 定义SD卡接口函数 */
  38. const Diskio_drvTypeDef  SD_Driver =
  39. {
  40.   SD_initialize,                   // SD卡初始化
  41.   SD_status,                       // SD卡状态获取
  42.   SD_read,                         // SD卡读数据
  43. #if  _USE_WRITE == 1
  44.   SD_write,                        // SD卡写数据
  45. #endif /* _USE_WRITE == 1 */
  46.   
  47. #if  _USE_IOCTL == 1
  48.   SD_ioctl,                         // 获取SD卡信息
  49. #endif /* _USE_IOCTL == 1 */
  50. };

  51. /* 函数体 --------------------------------------------------------------------*/
  52. /**
  53.   * 函数功能: SD卡初始化配置
  54.   * 输入参数: 无
  55.   * 返 回 值: 无
  56.   * 说    明: 无
  57.   */
  58. DSTATUS SD_initialize(BYTE lun)
  59. {
  60.   Stat = STA_NOINIT;
  61.   /* 初始化SDIO外设 */
  62.   MX_SDIO_SD_Init();
  63.   /* 获取SD卡状态 */
  64.   if(HAL_SD_GetStatus(&hsdcard)==SD_TRANSFER_OK)
  65.   {
  66.     Stat &= ~STA_NOINIT;
  67.   }
  68.   return Stat;
  69. }

  70. /**
  71.   * 函数功能: SD卡状态获取
  72.   * 输入参数: lun : 不用
  73.   * 返 回 值: DSTATUS:SD卡状态返回值
  74.   * 说    明: 无
  75.   */
  76. DSTATUS SD_status(BYTE lun)
  77. {
  78.   Stat = STA_NOINIT;

  79.   if(HAL_SD_GetStatus(&hsdcard) == SD_TRANSFER_OK)
  80.   {
  81.     Stat &= ~STA_NOINIT;
  82.   }
  83.   return Stat;
  84. }

  85. /**
  86.   * 函数功能: 从SD卡读取数据到缓冲区
  87.   * 输入参数: lun : 不用
  88.   *           buff:存放读取到数据缓冲区指针
  89.   *           sector:扇区地址(LBA)
  90.   *           count:扇区数目
  91.   * 返 回 值: DSTATUS:操作结果
  92.   * 说    明: SD卡读操作使用DMA传输
  93.   */
  94. DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
  95. {
  96.   DRESULT res = RES_OK;
  97.   if((DWORD)buff&3)
  98.   {
  99.     DWORD scratch[BLOCK_SIZE/4];
  100.     while (count--)
  101.     {
  102.       res = SD_read(lun,(void *)scratch, sector++, 1);
  103.       if (res != RES_OK)
  104.       {
  105.         break;
  106.       }
  107.       memcpy(buff, scratch, BLOCK_SIZE);
  108.       buff += BLOCK_SIZE;
  109.     }
  110.     return res;
  111.   }
  112.   
  113.   if(HAL_SD_ReadBlocks_DMA(&hsdcard,(uint32_t*)buff,(uint64_t)(sector * BLOCK_SIZE),BLOCK_SIZE,count) != SD_OK)
  114.   {
  115.     res = RES_ERROR;
  116.   }
  117.   if(res==RES_OK)
  118.   {
  119.     if(HAL_SD_CheckReadOperation(&hsdcard, 0xFFFFFFFF) != SD_OK)
  120.     {
  121.       res = RES_ERROR;
  122.     }
  123.   }
  124.   return res;
  125. }

  126. /**
  127.   * 函数功能: 将缓冲区数据写入到SD卡内
  128.   * 输入参数: lun : 不用
  129.   *           buff:存放待写入数据的缓冲区指针
  130.   *           sector:扇区地址(LBA)
  131.   *           count:扇区数目
  132.   * 返 回 值: DSTATUS:操作结果
  133.   * 说    明: SD卡写操作没有使用DMA传输
  134.   */
  135. #if _USE_WRITE == 1
  136. DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
  137. {
  138.   DRESULT res = RES_OK;
  139.   if((DWORD)buff&3)
  140.   {
  141.     DRESULT res = RES_OK;
  142.     DWORD scratch[BLOCK_SIZE / 4];

  143.     while (count--)
  144.     {
  145.       memcpy( scratch,buff,BLOCK_SIZE);
  146.       res = SD_write(lun,(void *)scratch, sector++, 1);
  147.       if (res != RES_OK)
  148.       {
  149.         break;
  150.       }                                       
  151.       buff += BLOCK_SIZE;
  152.     }
  153.     return res;
  154.   }        
  155.       
  156.   if(HAL_SD_WriteBlocks(&hsdcard,(uint32_t*)buff,(uint64_t)(sector * BLOCK_SIZE),BLOCK_SIZE, count) != SD_OK)
  157.   {
  158.     res = RES_ERROR;
  159.   }  
  160.   return res;
  161. }
  162. #endif /* _USE_WRITE == 1 */

  163. /**
  164.   * 函数功能: 输入输出控制操作(I/O control operation)
  165.   * 输入参数: lun : 不用
  166.   *           cmd:控制命令
  167.   *           buff:存放待写入或者读取数据的缓冲区指针
  168.   * 返 回 值: DSTATUS:操作结果
  169.   * 说    明: 无
  170.   */
  171. #if _USE_IOCTL == 1
  172. DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff)
  173. {
  174.   DRESULT res = RES_ERROR;
  175.   
  176.   if (Stat & STA_NOINIT) return RES_NOTRDY;
  177.   
  178.   switch (cmd)
  179.   {
  180.   /* Make sure that no pending write process */
  181.   case CTRL_SYNC :
  182.     res = RES_OK;
  183.     break;
  184.   
  185.   /* 获取SD卡总扇区数目(DWORD) */
  186.   case GET_SECTOR_COUNT :
  187.     HAL_SD_Get_CardInfo(&hsdcard,&SDCardInfo);
  188.     *(DWORD*)buff = SDCardInfo.CardCapacity / BLOCK_SIZE;
  189.     res = RES_OK;
  190.     break;
  191.   
  192.   /* 获取读写扇区大小(WORD) */
  193.   case GET_SECTOR_SIZE :
  194.     *(WORD*)buff = BLOCK_SIZE;
  195.     res = RES_OK;
  196.     break;
  197.   
  198.   /* 获取擦除块大小(DWORD) */
  199.   case GET_BLOCK_SIZE :
  200.     *(DWORD*)buff = BLOCK_SIZE;
  201.     break;
  202.   
  203.   default:
  204.     res = RES_PARERR;
  205.   }
  206.   
  207.   return res;
  208. }
  209. #endif /* _USE_IOCTL == 1 */
  210.   
  211. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

复制代码





小编的帖子质量很高。这个贴我用到,收藏了。

LZ,链接无效。

链接:https://pan.baidu.com/s/1slN8rIt 密码:u6m1

感谢

感谢

感谢

感谢

感谢

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top