STM32通过USB接口读写支持FATFS文件系统的挂载SD卡

通过USB接口读写挂载的SD卡

  • HAL库
  • 标准库
  • 本文以STM32F407为例分别用HAL库(STM32CubeMX)和标准库实现SD卡对fatfs支持,以及通过USB接口读写SD卡。首先看电路连接:

    SD卡部分:



    USB接口:

    HAL库

    这种方式相对较为简单,提供自动生成工具,几乎没有什么代码量,但其中也有一些细节需要注意,跟着如下操作吧:

    选择单片机型号(根据自己使用的片子选择):

    时钟和调试接口也根据自己板子设计选择:




    DMA这边添加首发通道,同时把数据类型修改为Byte:

    添加完后NVIC选项会多出两行:

    USB部分:

    使能中断:


    文件系统部分:



    还有重要的一步,这一步极为关键,就是中断优先级,大小关系得是SDIO global interrup >SDIO DMA > USB ,数字越小,优先级越高:

    配置系统时钟树(根据实际选择,这里选择外部8M晶振):



    最后生成项目:


    直接打开工程:


    根据情况配置下载参数:

    测试文件系统部分(缩减篇幅,删除了注释部分):

    uint8_t  readBuf[512];
    uint8_t  writeBuf[512];
    BYTE work[_MAX_SS];
    char *fileName = "test.txt";
    uint32_t writeLen;
    uint32_t readLen;
    
    int main(void)
    {
    	HAL_Init();
    	SystemClock_Config();
    	
    	MX_GPIO_Init();
    	MX_DMA_Init();
    	MX_SDIO_SD_Init();
    	MX_FATFS_Init();
    	MX_USB_DEVICE_Init();
    
    	// 挂载
    	retSD = f_mount(&SDFatFS, SDPath, 1);
    	switch(retSD)
    	{
    		case FR_NO_FILESYSTEM:  // FM_FAT32
    					{
    						retSD = f_mkfs(SDPath,FM_FAT32,512,work, sizeof(work));
    						if(retSD!=FR_OK)
    						{
    							while(1);
    						}
    					}
    					break;
    		case FR_OK:break;
    		default:
    			while(1);
    	}
    	
    	// 写
    	retSD = f_open(&SDFile,fileName, FA_CREATE_ALWAYS | FA_WRITE);
    	if(retSD!=FR_OK)
    	{
    		while(1);
    	}
    	
    	sprintf((char *)writeBuf,"%s","abc123今天天气还可以\r\n");
    	retSD = f_write(&SDFile,writeBuf, strlen((const char *)writeBuf), &writeLen);
    	if(retSD!=FR_OK)
    	{
    		while(1);
    	}
    	f_close(&SDFile);
    	
    	
    	// 读
    	retSD = f_open(&SDFile,fileName, FA_OPEN_EXISTING | FA_READ);
    	if(retSD!=FR_OK)
    	{
    		while(1);
    	}
    	
    	retSD = f_read(&SDFile,readBuf, 50, &readLen);
    	if(retSD!=FR_OK)
    	{
    		while(1);
    	}
    	f_close(&SDFile);
    	
    	// 卸载
    	f_mount(NULL, SDPath, 1);
    	while (1)
    	{
    	}
    }
    

    测试读写内容一致:

    SD卡使用读卡器插入电脑,文件内容与写入一致:

    USB部分还需要完善一些代码才可以使用,修改如下文件:

    #include "ff_gen_drv.h"
    


    然后就这个文件:

    全部代码如下,可直接复制替换,主要是添加头文件以及完善几个函数:

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : usbd_storage_if.c
      * @version        : v1.0_Cube
      * @brief          : Memory management layer.
      ******************************************************************************
      * @attention
      *
      * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
      * All rights reserved.</center></h2>
      *
      * This software component is licensed by ST under Ultimate Liberty license
      * SLA0044, the "License"; You may not use this file except in compliance with
      * the License. You may obtain a copy of the License at:
      *                             www.st.com/SLA0044
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    
    /* Includes ------------------------------------------------------------------*/
    #include "usbd_storage_if.h"
    
    /* USER CODE BEGIN INCLUDE */
    #include "sdio.h"
    #include "sd_diskio.h"
    /* USER CODE END INCLUDE */
    
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE END PV */
    
    /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
      * @brief Usb device.
      * @{
      */
    
    /** @defgroup USBD_STORAGE
      * @brief Usb mass storage device module
      * @{
      */
    
    /** @defgroup USBD_STORAGE_Private_TypesDefinitions
      * @brief Private types.
      * @{
      */
    
    /* USER CODE BEGIN PRIVATE_TYPES */
    
    /* USER CODE END PRIVATE_TYPES */
    
    /**
      * @}
      */
    
    /** @defgroup USBD_STORAGE_Private_Defines
      * @brief Private defines.
      * @{
      */
    
    #define STORAGE_LUN_NBR                  1
    #define STORAGE_BLK_NBR                  0x10000
    #define STORAGE_BLK_SIZ                  0x200
    
    /* USER CODE BEGIN PRIVATE_DEFINES */
    
    /* USER CODE END PRIVATE_DEFINES */
    
    /**
      * @}
      */
    
    /** @defgroup USBD_STORAGE_Private_Macros
      * @brief Private macros.
      * @{
      */
    
    /* USER CODE BEGIN PRIVATE_MACRO */
    
    /* USER CODE END PRIVATE_MACRO */
    
    /**
      * @}
      */
    
    /** @defgroup USBD_STORAGE_Private_Variables
      * @brief Private variables.
      * @{
      */
    
    /* USER CODE BEGIN INQUIRY_DATA_FS */
    /** USB Mass storage Standard Inquiry Data. */
    const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
    
      /* LUN 0 */
      0x00,
      0x80,
      0x02,
      0x02,
      (STANDARD_INQUIRY_DATA_LEN - 5),
      0x00,
      0x00,
      0x00,
      'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
      'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product      : 16 Bytes */
      ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
      '0', '.', '0' ,'1'                      /* Version      : 4 Bytes */
    };
    /* USER CODE END INQUIRY_DATA_FS */
    
    /* USER CODE BEGIN PRIVATE_VARIABLES */
    
    /* USER CODE END PRIVATE_VARIABLES */
    
    /**
      * @}
      */
    
    /** @defgroup USBD_STORAGE_Exported_Variables
      * @brief Public variables.
      * @{
      */
    
    extern USBD_HandleTypeDef hUsbDeviceFS;
    
    /* USER CODE BEGIN EXPORTED_VARIABLES */
    
    /* USER CODE END EXPORTED_VARIABLES */
    
    /**
      * @}
      */
    
    /** @defgroup USBD_STORAGE_Private_FunctionPrototypes
      * @brief Private functions declaration.
      * @{
      */
    
    static int8_t STORAGE_Init_FS(uint8_t lun);
    static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
    static int8_t STORAGE_IsReady_FS(uint8_t lun);
    static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
    static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
    static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
    static int8_t STORAGE_GetMaxLun_FS(void);
    
    /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
    
    /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
    
    /**
      * @}
      */
    
    USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
    {
      STORAGE_Init_FS,
      STORAGE_GetCapacity_FS,
      STORAGE_IsReady_FS,
      STORAGE_IsWriteProtected_FS,
      STORAGE_Read_FS,
      STORAGE_Write_FS,
      STORAGE_GetMaxLun_FS,
      (int8_t *)STORAGE_Inquirydata_FS
    };
    
    /* Private functions ---------------------------------------------------------*/
    /**
      * @brief  Initializes over USB FS IP
      * @param  lun:
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_Init_FS(uint8_t lun)
    {
      /* USER CODE BEGIN 2 */
      SD_Driver.disk_initialize(1);  // 增加
      return (USBD_OK);
      /* USER CODE END 2 */
    }
    
    /**
      * @brief  .
      * @param  lun: .
      * @param  block_num: .
      * @param  block_size: .
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
    {
      /* USER CODE BEGIN 3 */
      //*block_num  = STORAGE_BLK_NBR;
      //*block_size = STORAGE_BLK_SIZ;
      *block_num  = hsd.SdCard.BlockNbr ;
      *block_size = hsd.SdCard.BlockSize ;
      return (USBD_OK);
      /* USER CODE END 3 */
    }
    
    /**
      * @brief  .
      * @param  lun: .
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_IsReady_FS(uint8_t lun)
    {
      /* USER CODE BEGIN 4 */
      return (SD_Driver.disk_status(lun));
      /* USER CODE END 4 */
    }
    
    /**
      * @brief  .
      * @param  lun: .
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
    {
      /* USER CODE BEGIN 5 */
      return (USBD_OK);
      /* USER CODE END 5 */
    }
    
    /**
      * @brief  .
      * @param  lun: .
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 6 */
      return (SD_Driver.disk_read(lun, buf, blk_addr, blk_len));
      /* USER CODE END 6 */
    }
    
    /**
      * @brief  .
      * @param  lun: .
      * @retval USBD_OK if all operations are OK else USBD_FAIL
      */
    int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 7 */
      return (SD_Driver.disk_write(lun, buf, blk_addr, blk_len));
      /* USER CODE END 7 */
    }
    
    /**
      * @brief  .
      * @param  None
      * @retval .
      */
    int8_t STORAGE_GetMaxLun_FS(void)
    {
      /* USER CODE BEGIN 8 */
      return (STORAGE_LUN_NBR - 1);
      /* USER CODE END 8 */
    }
    
    /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
    
    /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    

    然后编译下载,使用USB线连接单片机和电脑,即可在电脑上通过USB读写SD卡里内容了:

    标准库

    未完…

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32通过USB接口读写支持FATFS文件系统的挂载SD卡

    发表评论